Regex Named Capture Groups — Every Syntax
Most modern engines use (?<name>...); Python historically uses (?P<name>...) and also accepts it in PCRE. Here is the syntax and how you actually read the value in each language.
Define syntax by engine
| Engine | Define | Backreference |
|---|---|---|
| JavaScript (ES2018) | (?<year>\d{4}) | \k<year> |
| Python | (?P<year>\d{4}) | (?P=year) |
| Java | (?<year>\d{4}) | \k<year> |
| PHP / PCRE | (?<year>...) or (?P<year>...) | (?P=year) |
| .NET | (?<year>\d{4}) | \k<year> |
| Go (RE2) | (?P<year>\d{4}) | none (no backrefs) |
Read the value in your code
# Python
import re
m = re.search(r'(?P<year>\d{4})-(?P<month>\d{2})', '2026-09')
m.group('year') # -> '2026'
m.groupdict() # -> {'year': '2026', 'month': '09'}
// JavaScript
const m = '2026-09'.match(/(?<year>\d{4})-(?<month>\d{2})/);
m.groups.year; // -> '2026'
Why bother with names?
Numeric groups break the moment you insert a new group earlier in the pattern — every index shifts. Named groups are stable, self-documenting, and let you build a dictionary of results in one call (groupdict() in Python, .groups in JS). For any regex you will revisit, names pay for themselves.
Portability tip
The (?<name>...) form is the widest-supported today. Python accepted only (?P<name>...) for years, so if you copy a pattern from Python docs into JavaScript, rewrite (?P<name>...) to (?<name>...) and (?P=name) to \k<name>.
FAQ
What is the difference between (?<name>) and (?P<name>)?
They mean the same thing — a named capture group. (?<name>) is the ECMAScript/.NET/Java/PCRE form; (?P<name>) is the Python form, also accepted by PCRE and Go's RE2.
How do I reference a named group later in the same pattern?
Use \k<name> in JavaScript, Java and .NET, or (?P=name) in Python and PCRE. Go's RE2 has no backreferences at all.
Do named groups work in JavaScript?
Yes, since ES2018. Define with (?<name>...) and read the result from match.groups.name.