Capturing groups

re · Essentials · 9 min

Extracting fields such as dates, IDs or key-value pairs is the main reason to use regex.

Parentheses do two jobs: they group items for quantifiers and alternation, and they capture the text they match.

Groups are numbered by their opening parenthesis from left to right, starting at 1:

m = re.search(r"(\d{4})-(\d{2})-(\d{2})", "due 2025-03-01")
m.group(1)   # '2025'
m.groups()   # ('2025', '03', '01')

m.group(0) is the whole match; m.group(1, 3) returns a tuple of several groups. A group that didn't participate (for example inside an optional part) returns None.

If you need parentheses just for grouping, use a non-capturing group (?:...). It keeps numbering simple and is slightly faster: r"(?:https?://)?(\w+\.com)" captures only the domain.

Groups also change what other functions return, which surprises people: re.findall returns the group contents instead of the whole match when the pattern has groups, and re.split includes captured separators in the result.

Inside the pattern, \1 refers back to whatever group 1 matched, so r"\b(\w+) \1\b" finds doubled words like "the the".

Example

import re

m = re.search(r"(\d{4})-(\d{2})-(\d{2})", "due 2025-03-01, paid")
print(m.group(0))            # 2025-03-01
print(m.group(1), m[2])      # 2025 03
print(m.groups())            # ('2025', '03', '01')
year, month, day = map(int, m.groups())
print(year + 1)              # 2026

m = re.search(r"(?:https?://)?([\w.]+\.com)(/\S*)?", "see example.com now")
print(m.groups())            # ('example.com', None)

print(re.search(r"\b(\w+) \1\b", "it was the the end").group(1))  # the

Remember

  • Each ( ) captures; numbering follows the opening parentheses
  • Use (?:...) when you only need grouping
  • Groups that didn't take part in the match return None

Watch out for

  • Adding a capturing group to a pattern used with findall and suddenly getting only the group's text back.

Check yourself

  1. For re.search(r'(a)(b)?(c)', 'ac'), what is m.groups()?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.python.org/3/library/re.html#re.Match.group