Named groups
Assign readable names to capturing groups with (?<name>…) so match results can be accessed by name instead of position.
- Write a named capturing group using (?<name>…) syntax
- Access a named group's value from the match result
- Explain when named groups are preferable to numbered groups
When a pattern has more than two or three groups, positional indices become a maintenance burden. Renaming the pattern later means renumbering everything that reads from it. Named groups solve this by letting you attach a label directly to each group.
Syntax
Use (?<name>…) — a question mark, angle brackets around the name, then the
pattern:
const m = "2024-03-15".match(/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/);
// Positional (still works)
console.log(m[1]); // "2024"
// By name — via the match object's groups property
console.log(m.groups.year); // "2024"
console.log(m.groups.month); // "03"
console.log(m.groups.day); // "15"The groups property of the match result is a plain object containing all named
groups. Unnamed groups do not appear in groups.
Destructuring named groups
You can destructure directly from m.groups:
const { year, month, day } = "2024-03-15".match(
/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/
).groups;
console.log(year, month, day); // "2024" "03" "15"This is the cleanest way to consume a named-group match in modern JavaScript.
Named groups in Python
Python uses the same (?P<name>…) syntax (note the P — a historical quirk):
import re
m = re.search(r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})", "2024-03-15")
m.group("year") # "2024"
m.group("month") # "03"
m.groupdict() # {"year": "2024", "month": "03", "day": "15"}JavaScript added (?<name>…) syntax in ES2018. Python's (?P<name>…) has been
available since Python 2.7. The meaning is the same; only the delimiter differs.
When to use named groups
Use named groups when:
- The pattern has three or more capturing groups
- The groups are reused in multiple places in your codebase
- The pattern may change and you want the call sites to stay stable
- You are writing code that will be read (and maintained) by someone else
Numbered groups are fine for short, one-off patterns. Once a pattern grows or is used in multiple places, names pay dividends quickly.
Named groups with matchAll
Named groups work with matchAll the same way they work with match:
const re = /(?<host>[\w.-]+)\s+(?<status>\d{3})/g;
const log = "example.com 200\nother.org 404\nthird.net 200";
for (const m of log.matchAll(re)) {
const { host, status } = m.groups;
console.log(`${host} returned ${status}`);
}Named groups in replace
Named groups can be referenced in replacement strings using $<name>:
// Reformat YYYY-MM-DD to DD/MM/YYYY
"2024-03-15".replace(
/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/,
"$<day>/$<month>/$<year>"
);
// "15/03/2024"In Python, use \g<name> in the replacement:
import re
re.sub(r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})",
r"\g<day>/\g<month>/\g<year>",
"2024-03-15")
# "15/03/2024"Where to go next
Next: non-capturing groups — (?:…) gives you grouping for quantifiers and
alternation without the overhead of capturing.
Capturing groups
Use parentheses to capture matched text for extraction and reuse — the fundamental mechanism behind regex-based data extraction.
Non-capturing groups
Group patterns for quantifiers and alternation without creating a capture — keeping group numbering clean and avoiding unnecessary overhead.