Named groups in Python's re module allow you to assign a name to a capturing group, making it easier to reference the matched text by name rather than by number. This improves code readability and maintainability, especially in complex regular expressions.

Syntax

  • Use (?P<name>pattern) to define a named group, where name is a valid Python identifier (e.g., (?P<timestamp>\d+)).

  • Reference the group using match.group('name') or (?P=name) in the same regex for backreferences.

Example

import re

log = "[2025-06-09 14:23:01] INFO - OrderID: #A1B2C3, Customer: John Doe (CA), Total: $49.99"
pattern = r'\[(?P<timestamp>.*?)\] .*?OrderID: (?P<order_id>\#\w+), Customer: (?P<name>[A-Za-z ]+) $$(?P<state>\w{2})$$, Total: \$(?P<total>[0-9]+\.[0-9]{2})'

match = re.search(pattern, log)
if match:
    print(match.group('timestamp'))   # Output: 2025-06-09 14:23:01
    print(match.group('order_id'))    # Output: #A1B2C3
    print(match.group('name'))        # Output: John Doe
    print(match.group('state'))       # Output: CA
    print(match.group('total'))       # Output: 49.99

Key Features

  • Named groups are also numbered: They can be accessed via both name and index (e.g., group(1) and group('name')).

  • match.groupdict() returns a dictionary of all named groups and their matched values.

  • Backreferences: Use (?P=name) to match the same text captured by a named group (e.g., (?P<word>\w+) \1 matches repeated words).

Benefits

  • Readability: Code is self-documenting when group names describe their purpose.

  • Maintainability: Adding or removing groups doesn’t break existing code if you use names instead of numbers.

  • Consistency: Python’s re module was the first to introduce this feature, and it’s now widely supported across many regex flavors.

For more details, refer to the official Python re module documentation.

You can either read the entire file into a list, then filter that list, or you could process it line by line and process each matching line. For example (using my file) · for line in open('usblog.txt'): · if '2024-01-24' in line: · print(line) · or · text = open('usblog.txt').readlines() · for line in [x for x in text if '2024-01-24' in x]: · print(line) · if · · only appears in the lines you want then filter on that. Answer from reverend-jim on daniweb.com
🌐
Quora
quora.com › How-do-you-extract-matching-groups-from-a-string-in-Python-Regex
How to extract matching groups from a string in Python Regex - Quora
Answer: Example: [code]# import ... = “([A-Za-z]*\$)([\s][0-9]+)[\.]([0-9]{2})” # We will get 3 groups reg_groups = re.search(pattern, full_string) # The ......
🌐
Semantic Versioning
semver.org
Semantic Versioning 2.0.0 | Semantic Versioning
And one with numbered capture groups instead (so cg1 = major, cg2 = minor, cg3 = patch, cg4 = prerelease and cg5 = buildmetadata) that is compatible with ECMA Script (JavaScript), PCRE (Perl Compatible Regular Expressions, i.e. Perl, PHP and R), Python and Go.
🌐
Imperial College London
python.pages.doc.ic.ac.uk › 2021 › lessons › regex › 07-groups › 01-group.html
Advanced Lesson 1: Regular Expressions > Capturing groups
You can actually retrieve the content of a group after matching. This is useful if you need to extract the specific substrings that match your pattern. Below is an example use case. You might want to retrieve some information about that crazy lecturer of yours. Try it out yourself! And make sure you understand what each output represents. Consult the documentation otherwise. >>> pattern = "Name: ([A-Za-z ]+); Phone: (\d+); Position: (.+)" >>> string = "Name: Josiah Wang; Phone: 012345678; Position: Senior Teaching Fellow" >>> match = re.match(pattern, string) >>> print(match) <re.Match object;
🌐
Mozilla
developer.mozilla.org › en-US › docs › Web › JavaScript › Guide › Regular_expressions › Groups_and_backreferences
Groups and backreferences - JavaScript | MDN
January 8, 2026 - Groups group multiple patterns as a whole, and capturing groups provide extra submatch information when using a regular expression pattern to match against a string. Backreferences refer to a previously captured group in the same regular expression.
🌐
Python documentation
docs.python.org › 3 › library › re.html
re — Regular expression operations
4 days ago - The regex matching flags. This is a combination of the flags given to compile(), any (?...) inline flags in the pattern, and implicit flags such as UNICODE if the pattern is a Unicode string. ... The number of capturing groups in the pattern. ... A dictionary mapping any symbolic group names defined by (?P<id>) to group numbers.
🌐
SitePoint
sitepoint.com › blog › programming › understanding python regex functions, with examples
Understanding Python Regex Functions, with Examples — SitePoint
November 13, 2024 - regex_object = re.search('^J\w+', 'Popular programming languages in 2022: \nPython \nJavaScript \nJava \nRust \nRuby', re.M) print(regex_object.group()) >>>> JavaScript · Sometimes, Python regex patterns can get long and messy. The re.X flag helps out when we need to add comments within our regex pattern. We can use the ''' string format to create a multiline regex with comments: email_regex = re.search(r''' [a-zA-Z0-9._%+-]+ # username composed of alphanumeric characters @ # @ symbol [a-zA-Z0-9.-]+ # domain name has word characters (\.[a-zA-Z]{2,4}) # dot-something ''', 'extract the email address in this string kwekujohnson1@gmail.co and send an email', re.X) print(email_regex.group()) >>>> kwekujohnson1@gmail.co
Find elsewhere
🌐
Visual Studio Code
code.visualstudio.com › docs › getstarted › tips-and-tricks
Visual Studio Code tips and tricks
November 3, 2021 - Enable regular expressions in the search box by clicking the Use Regular Expression .* button (⌥⌘R (Windows, Linux Alt+R)) and then write a regular expression and use parentheses to define groups.
🌐
Home Assistant
home-assistant.io › docs › configuration › templating
Templating - Home Assistant
For more information on regular expressions See: Python regular expression operations · Test string is match(find, ignorecase=False) will match the find expression at the beginning of the string using regex. Test string is search(find, ignorecase=False) will match the find expression anywhere in the string using regex. Filter string|regex_replace(find='', replace='', ignorecase=False) will replace the find expression with the replace string using regex. Access to the matched groups in replace is possible with '\\1', '\\2', and so on.
🌐
PyPI
pypi.org › project › fastapi
fastapi · PyPI
How to set validation constraints as maximum_length or regex.
      » pip install fastapi
    
Published   Mar 01, 2026
Version   0.135.1
Top answer
1 of 3
457

Since we're all guessing, I might as well give mine: I've always thought it stood for Python. That may sound pretty stupid -- what, P for Python?! -- but in my defense, I vaguely remembered this thread [emphasis mine]:

Subject: Claiming (?P...) regex syntax extensions

From: Guido van Rossum ([email protected])

Date: Dec 10, 1997 3:36:19 pm

I have an unusual request for the Perl developers (those that develop the Perl language). I hope this (perl5-porters) is the right list. I am cc'ing the Python string-sig because it is the origin of most of the work I'm discussing here.

You are probably aware of Python. I am Python's creator; I am planning to release a next "major" version, Python 1.5, by the end of this year. I hope that Python and Perl can co-exist in years to come; cross-pollination can be good for both languages. (I believe Larry had a good look at Python when he added objects to Perl 5; O'Reilly publishes books about both languages.)

As you may know, Python 1.5 adds a new regular expression module that more closely matches Perl's syntax. We've tried to be as close to the Perl syntax as possible within Python's syntax. However, the regex syntax has some Python-specific extensions, which all begin with (?P . Currently there are two of them:

(?P<foo>...) Similar to regular grouping parentheses, but the text
matched by the group is accessible after the match has been performed, via the symbolic group name "foo".

(?P=foo) Matches the same string as that matched by the group named "foo". Equivalent to \1, \2, etc. except that the group is referred
to by name, not number.

I hope that this Python-specific extension won't conflict with any future Perl extensions to the Perl regex syntax. If you have plans to use (?P, please let us know as soon as possible so we can resolve the conflict. Otherwise, it would be nice if the (?P syntax could be permanently reserved for Python-specific syntax extensions. (Is there some kind of registry of extensions?)

to which Larry Wall replied:

[...] There's no registry as of now--yours is the first request from outside perl5-porters, so it's a pretty low-bandwidth activity. (Sorry it was even lower last week--I was off in New York at Internet World.)

Anyway, as far as I'm concerned, you may certainly have 'P' with my blessing. (Obviously Perl doesn't need the 'P' at this point. :-) [...]

So I don't know what the original choice of P was motivated by -- pattern? placeholder? penguins? -- but you can understand why I've always associated it with Python. Which considering that (1) I don't like regular expressions and avoid them wherever possible, and (2) this thread happened fifteen years ago, is kind of odd.

2 of 3
50

Python Extension. From the Python Docs:

The solution chosen by the Perl developers was to use (?...) as the extension syntax. ? immediately after a parenthesis was a syntax error because the ? would have nothing to repeat, so this didn’t introduce any compatibility problems. The characters immediately after the ? indicate what extension is being used, so (?=foo) is one thing (a positive lookahead assertion) and (?:foo) is something else (a non-capturing group containing the subexpression foo).

Python supports several of Perl’s extensions and adds an extension syntax to Perl’s extension syntax.If the first character after the question mark is a P, you know that it’s an extension that’s specific to Python

https://docs.python.org/3/howto/regex.html

🌐
Python documentation
docs.python.org › 3 › howto › regex.html
Regular Expression HOWTO — Python 3.14.3 documentation
The syntax for a named group is one of the Python-specific extensions: (?P<name>...). name is, obviously, the name of the group. Named groups behave exactly like capturing groups, and additionally associate a name with a group.
🌐
Plain English
python.plainenglish.io › capturing-groups-in-python-regex-real-world-example-7655e6c645d2
Capturing Groups in Python Regex : Real-World Example | by Prathik C | Python in Plain English
July 22, 2025 - pattern = r'\[(?P<timestamp>.*?)\] .*?OrderID: (?P<order_id>\#\w+), Customer: (?P<name>[A-Za-z ]+) \((?P<state>\w{2})\), Total: \$(?P<total>[0-9]+\.[0-9]{2})' match = re.search(pattern, log) if match: print(match.group('timestamp')) print(match.group('order_id')) print(match.group('name')) print(match.group('state')) print(match.group('total')) ... Capturing groups take regex from a blunt instrument to a scalpel. With them, you can extract and manipulate text at a granular level. Start small, but aim for complex, structured parsing problems — because that’s where the real value of regex kicks in. ... New Python content every day.
🌐
RegexOne
regexone.com › lesson › capturing_groups
RegexOne - Learn Regular Expressions - Lesson 11: Match groups
Regular expressions allow us to not just match text but also to extract information for further processing. This is done by defining groups of characters and capturing them using the special parentheses ( and ) metacharacters. Any subpattern inside a pair of parentheses will be captured as a group.
🌐
Spark By {Examples}
sparkbyexamples.com › home › python › python regex replace with capture group
Python regex replace with capture group - Spark By {Examples}
May 31, 2024 - The replacement pattern \2, \1 refers to the second and first captured groups, resulting in the desired name reversal. ... As you are working with capture groups you may want to reuse them at some point. So to access them from the pattern in the replacement pattern string, simply use backreferences. Here’s an example that demonstrates how to access capture groups in the replacement pattern: import re # the original text text = "On 2012-12-12, SparkByExamples was launched" # define the regex pattern with a capture group for the date pattern = r"(\d{4})-(\d{2})-(\d{2})" # specify the replacement pattern with access to the capture groups replacement = r"Year: \1, Month: \2, Day: \3" # perform the replacement using re.sub() new_text = re.sub(pattern, replacement, text) # print the modified text print(new_text)
🌐
Narkive
boost-users.boost.narkive.com › cgYLGLuB › boost-regex-iterate-over-named-captures-groups
Boost.Regex: Iterate over named captures/groups
Post by NoRulez if I have a regex (e.g.: "^Subject: (Re: |Fw: )*(?<subject>.*)") I know I can access them with what["subject"] but is there a way to get a list or whatever of named captures/groups? What would you expect to see? You asked for a named group "subject", which matches zero or more characters; as such, it will *always* match (if the whole match succeeds) but it might be empty.
🌐
Timothygebhard
timothygebhard.de › posts › named-groups-in-regex-in-python
Named groups for regex in Python · Timothy Gebhard
I figured that maybe it is about time I just write down the correct syntax myself once, so that either my brain will now remember it, or that I at least know where to look it so. So without further ado, here’s the example code for named group using Python’s re module:
🌐
Regular-Expressions.info
regular-expressions.info › named.html
Regex Tutorial: Named Capturing Groups - Backreference Names
The .NET syntax with angle brackets is supported since the 2023-09-01 release. Since RE2 uses a text-directed engine, it does not support backreferences at all. You can use RE2::NamedCapturingGroups() to retrieve matches of named capturing groups in your code after the regex has found a match.
🌐
Imperial College London
python.pages.doc.ic.ac.uk › lessons › regex › 07-groups › 02-named.html
Advanced Lesson 1: Regular Expressions > Named groups
>>> pattern = "Name: (?P<name>[A-Za-z ]+); Phone: (?P<phone>\d+)" >>> string = "Name: Josiah Wang; Phone: 012345678" >>> match = re.match(pattern, string) >>> print(match) <re.Match object; span=(0, 35), match='Name: Josiah Wang; Phone: 012345678'> >>> match.group("name") 'Josiah Wang' >>> match.group("phone") '012345678' >>> match.group(1) 'Josiah Wang' >>> match.group(2) '012345678' >>> match.groupdict() {'name': 'Josiah Wang', 'phone': '012345678'}