iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Named Groups

Named groups ((?<name>…)) replace numeric backreferences with self-documenting captures. They survive pattern edits, work in match / matchAll / replace, and read better in code review.

Capture, reference, replace

EXAMPLE
// 1) Capture with names — accessible via .groups
const m = '2026-06-07'.match(/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/);
console.log(m.groups.year, m.groups.month, m.groups.day);
// '2026' '06' '07'

// 2) Backreference by name
/(?<quote>['"]).*?\k<quote>/.test(`"foo"`); // true
/(?<quote>['"]).*?\k<quote>/.test(`'foo"`); // false — quotes differ

// 3) Replace with named refs ($<name>)
'first last'.replace(/(?<first>\w+) (?<last>\w+)/, '$<last>, $<first>');
// 'last, first'

// 4) matchAll — iterate over all matches with .groups
const log = `[12:00:01] INFO ok\n[12:00:02] ERROR boom\n[12:00:03] INFO done`;
for (const m of log.matchAll(/\[(?<ts>[\d:]+)\] (?<level>\w+) (?<msg>.*)/g)) {
    console.log(m.groups);
    // { ts: '12:00:01', level: 'INFO', msg: 'ok' }
}

// 5) Optional named groups + destructuring
const pat = /^(?<scheme>https?):\/\/(?<host>[^/]+)(?<path>\/[^?]*)?(?:\?(?<query>.*))?$/;
const { groups } = pat.exec('https://api.example.com/users?id=42');
const { scheme, host, path, query = '' } = groups ?? {};
console.log(scheme, host, path, query);

// 6) Mix anonymous + named groups (named groups count as captures too)
/(?<year>\d{4})-(\d{2})-(\d{2})/.exec('2026-06-07')
//   .groups.year   = '2026'
//   [1]            = '2026'
//   [2]            = '06'
//   [3]            = '07'

// 7) Cross-language gotcha — different syntaxes
//   JS / Python / .NET / PCRE: (?<name>...)
//   Python:                       also (?P<name>...) — backwards compatible
//   Java:                          (?<name>...)
//   Replacement refs:
//     JS / .NET:    $<name>
//     Python:        \\g<name>
//     Java:           ${name} (in Matcher.appendReplacement)

Why it matters

Switch any regex with 3+ captures to named groups. The pattern stays the same, but the code that reads m.groups.year survives changes that m[1] wouldn’t.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
const m = '2026-06-07'.match(/(?<y>\d{4})-(?<m>\d{2})-(?<d>\d{2})/);
'2026-06-07'.replace(/(?<y>\d{4})-(?<m>\d{2})-(?<d>\d{2})/, '$<d>/$<m>/$<y>');
Try it Yourself »

Exercise

JS named-group syntax for "year".

/(? year>\\d{4})/

Discussion

Loading…