Backreferences inside the pattern

Regular expressions · Advanced · 10 min

Backreferences match 'the same thing again', which no character class or quantifier can express.

A backreference in the pattern itself matches exactly the text a group captured earlier in the same match. (\w+) \1 finds a doubled word like the the. Named versions are (?P=name) in Python and \k<name> in PCRE, JavaScript, Java and .NET.

Common uses:

  • Repeated words in prose: \b(\w+)\s+\1\b with the ignore-case flag.
  • Matching quotes: (["'])(.*?)\1 accepts "x" and 'x' but not "x'.
  • Paired simple delimiters: <(\w+)>.*?</\1> for non-nested tags.
  • Repeated characters: (.)\1{2,} finds any character repeated three or more times.

Things to know:

  • A backreference matches the text, not the pattern: (\d)\1 matches 55, not 56.
  • If the group didn't participate, Python fails the backreference, while JavaScript lets it match the empty string.
  • Backreferences take regexes beyond regular languages. They make matching NP-hard in general, which is why RE2, Go and Rust leave them out and why they can be slow in grep.
  • Don't confuse them with replacement references: \1 in the replacement string of re.sub is a different (simpler) mechanism.

Example

import re

text = "This is the the test, and and it works"
print(re.findall(r"\b(\w+)\s+\1\b", text))           # ['the', 'and']

print(re.findall(r'(["\'])(.*?)\1', ' "a" \'b\' "c\' '))  # [('"', 'a'), ("'", 'b')]

print(bool(re.fullmatch(r"<(\w+)>.*?</\1>", "<b>bold</b>")))    # True
print(bool(re.fullmatch(r"<(\w+)>.*?</\1>", "<b>bold</i>")))    # False

print(re.findall(r"((.)\2{2,})", "aaxyyyyz111"))     # [('yyyy', 'y'), ('111', '1')]
print(bool(re.fullmatch(r"(?P<d>\d)(?P=d)", "55")))  # True

Remember

  • \1 inside the pattern matches the same text group 1 captured
  • Named form: (?P=name) in Python, \k<name> elsewhere
  • Backreferences are unsupported in RE2, Go and Rust and can be slow

Watch out for

  • Expecting (\d)\1 to match any two digits; it matches only a repeated digit.

Check yourself

  1. Which strings does ^(ab|cd)\1$ match?

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#regular-expression-syntax

Builds on

Unlocks

Nothing builds on this yet.