(?<name>…), (?P<name>…), (?'name'…) — three ways to name a group, four to refer to it¶
One line: A named group is a capturing group you refer to by a word instead of a number, and it is the single most portable-looking, least-portable feature in the language: (?<w>…) is refused by Python 3.12, (?P<w>…) is refused by JavaScript, Ruby and Java, and the backreference to a name is \k<w> in five engines and (?P=w) in Python — with no spelling that all eight accept.
Level: reference · one construct, eight engines
What it means¶
Numbers change when a pattern is edited; names do not. That is the whole case for naming, and it is a strong one. The cost is the spelling war:
| To define | Accepted by |
|---|---|
(?<w>…) |
Perl, PCRE2, JavaScript, Ruby, Java, Go, Rust, fancy-regex — not Python 3.12 |
(?P<w>…) |
Python, Perl, PCRE2, Go, Rust, fancy-regex — not JavaScript, Ruby, Java |
(?'w'…) |
Perl, PCRE2, Ruby, fancy-regex |
| To match the same text again | Accepted by |
|---|---|
\k<w> |
Perl, PCRE2, JavaScript, Ruby, Java, fancy-regex |
(?P=w) |
Python, Perl, PCRE2, fancy-regex |
\g{w} |
Perl, PCRE2 |
\k'w', \k{w} |
Perl, PCRE2, (Ruby for \k'w') |
Go and Rust's regex can define names and cannot refer to one in the pattern at all — no backreferences — but both use ${w} in a replacement.
Measured¶
Verified output of kw_named_group_sh.sh — regenerated by tools/run_examples.py, never hand-typed.
construct python perl node ruby java go rust fancy
(?<w>...) - a a a a a a a
(?P<w>...) a a - - - a a a
(?'w'...) - a - a - - - a
\k<w> backreference - aa aa aa aa - - aa
(?P=w) backreference aa aa - - - - - aa
\g{w} backreference - aa no no - - - -
same name twice - b n/a b - b - b
Reading the table¶
- Row 1,
(?<w>a). Seven engines; Python is-. Python'sreaccepts(?<=and(?<!for lookbehind and nothing else after(?<. (Python 3.12 is what the probe runs; the same is true of 3.14.) - Row 2,
(?P<w>a). Python's own spelling, adopted by PCRE2 — so ABAP — and by Go and Rust, both of which accept both. JavaScript, Ruby and Java refuse it. - Row 3,
(?'w'a). Perl, Ruby andfancy-regexonly. Rarely worth writing. - Rows 4–6, referring back.
\k<w>works in six engines;(?P=w)in Python, Perl andfancy-regex;\g{w}in Perl alone — and JavaScript and Ruby compile\g{w}and match nothing, reading it as the literal textg{w}. Go and Rust refuse all three, correctly: they have no backreferences of any kind. - Row 7, the same name twice. Perl, Ruby, Go and
fancy-regexallow(?<w>a)|(?<w>b)— one name, two alternatives, whichever matched. Python, Java and Rust'sregexrefuse. JavaScript isn/a: duplicate names in different alternatives are a post-ES2018 addition that Node 20 and Node 24 answer differently, so the driver did not ask.
The trap¶
The (?P<…> / (?<…> split, in both directions. A Python pattern with (?P<year>\d{4}) is a syntax error in JavaScript, Ruby and Java; a JavaScript pattern with (?<year>\d{4}) is a syntax error in Python. Neither error message says "use the other spelling". PCRE2, Perl, Go and Rust accept both, which is why a pattern tested in pcre2grep or in Go can still fail in one of the two languages it was destined for.
Where it is measured in depth¶
- Who supports what — the
named backrefrows that this page grew out of. - What a backreference is.
See also¶
- Capturing group · Backreference · Replacement references —
${w},$<w>,\k<w>,\g<w>on the replacement side, which is a fourth spelling war. - Readable patterns · Portability between engines.