Introduction
Groups let you extract parts of a match, apply quantifiers to multiple characters, and create backreferences. Named groups make patterns self-documenting. These features transform regex from pattern matching to powerful text extraction.
Key Concepts
Capturing Group: () captures matched text for later use.
Non-capturing Group: (?:) groups without capturing.
Named Group: (?<name>) captures with a descriptive name.
Deep Dive
Basic Groups
javascript// Capturing groups const match = 'John Smith'.match(/(\w+) (\w+)/); match[0]; // 'John Smith' (full match) match[1]; // 'John' (first group) match[2]; // 'Smith' (second group) // Group quantifiers /(ab)+/.test('ababab'); // true (matches 'ab' one or more times) // Alternation within groups /(cat|dog)/.test('I have a cat'); // true
Named Groups (ES2018)
javascriptconst dateRegex = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/; const match = '2024-12-25'.match(dateRegex); match.groups.year; // '2024' match.groups.month; // '12' match.groups.day; // '25' // Destructuring const { groups: { year, month, day } } = '2024-12-25'.match(dateRegex);
Non-capturing Groups
javascript// When you need grouping but don't need the capture /(?:ab)+/.test('ababab'); // true // Compare: 'ababab'.match(/(ab)+/); // ['ababab', 'ab'] (captures last 'ab') 'ababab'.match(/(?:ab)+/); // ['ababab'] (no extra capture)
Backreferences
javascript// Reference earlier capture /(\w+) and \1/.test('cat and cat'); // true /(\w+) and \1/.test('cat and dog'); // false // Named backreference /(?<word>\w+) and \k<word>/.test('cat and cat'); // true // Find duplicated words /\b(\w+)\s+\1\b/.test('the the'); // true
Using Groups in Replace
javascript// Numbered groups 'John Smith'.replace(/(\w+) (\w+)/, '$2, $1'); // 'Smith, John' // Named groups '2024-12-25'.replace( /(?<y>\d{4})-(?<m>\d{2})-(?<d>\d{2})/, '$<m>/$<d>/$<y>' ); // '12/25/2024' // With function 'hello world'.replace(/(\w+)/g, (match, p1) => p1.toUpperCase()); // 'HELLO WORLD'
matchAll() for Multiple Matches
javascriptconst regex = /(\w+)@(\w+\.\w+)/g; const text = 'Contact: alice@example.com, bob@test.org'; for (const match of text.matchAll(regex)) { console.log(match[0]); // Full email console.log(match[1]); // Username console.log(match[2]); // Domain }
Common Pitfalls
- Too many captures slow matching: Use
(?:)when you don't need the value. - Backreference numbering: Groups are numbered left-to-right by opening paren.
- Global flag with match(): Returns array of matches, not groups. Use
matchAll().
Best Practices
- Use named groups for readability:
(?<year>\d{4})is self-documenting. - Use non-capturing groups for alternation:
(?:cat|dog)when you don't need capture. - Use matchAll() for extraction: Gives all matches with all groups.
Summary
Capturing groups () extract matched text. Named groups (?<name>) add clarity. Non-capturing groups (?:) group without overhead. Backreferences (\1, \k<name>) match earlier captures. Use $1 or $<name> in replacements.
Code Examples
javascript
// Capturing groups
const match = 'John Smith'.match(/(\w+) (\w+)/);
match[0]; // 'John Smith' (full match)
match[1]; // 'John' (first group)
match[2]; // 'Smith' (second group)
// Group quantifiers
/(ab)+/.test('ababab'); // true (matches 'ab' one or more times)
// Alternation within groups
/(cat|dog)/.test('I have a cat'); // truejavascript
const dateRegex = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const match = '2024-12-25'.match(dateRegex);
match.groups.year; // '2024'
match.groups.month; // '12'
match.groups.day; // '25'
// Destructuring
const { groups: { year, month, day } } = '2024-12-25'.match(dateRegex);