本页面有中文版。
Cette page est disponible en français.
Esta página está disponible en español.
Guides1 live hunt inside

Regex backreferences: patterns that remember what they matched

A backreference like \1 matches the exact text a group already captured. Here's how they work, how to find doubled letters, repeated words and palindromes, and the one place they don't work.

Regex Hunter logo

· 6 min read

/(.)\1/

match

  • book
  • letter
  • coffee

spare

  • cat
  • dog
  • lemon

Most of a regex describes kinds of text: a digit, a letter, any character. A backreference is different. It says "the same text I matched a moment ago". That one idea lets a short pattern find doubled letters, repeated words and palindromes, which no character class can describe.

Every example below is live. Edit the pattern, or hit Try it to open it in the Playground.

01Capture first, then refer back

Parentheses do two jobs: they group, and they capture. Whatever text a group matches is saved, numbered from left to right by its opening parenthesis. \1 means "the text group 1 captured", \2 the second group, and so on.

Matches6/6 as expected
/(.)\1/

Should match3/3

  • book
  • letter
  • coffee

Should not3/3

  • cat
  • dog
  • lemon
Try it in the Playground
(.) captures one character, and \1 asks for that same character again. Any doubled letter matches.

The key word is same text. (\w)\w means "a letter, then any letter", so it matches almost everything. (\w)\1 means "a letter, then that exact letter again". The backreference doesn't repeat the pattern inside the group. It repeats the result.

02Repeated words

A classic proofreading bug is the doubled word: "the the". Capture a word, then ask for a space and the same word:

Matches4/4 as expected
/\b(\w+) \1\b/

Should match2/2

  • this is the the end
  • it is is fine

Should not2/2

  • the then
  • that is it
Try it in the Playground
The \b at each end keeps it to whole words, so "the then" doesn't count as "the" twice.

Without the final \b, the then would match: the, a space, then the the at the start of then.

03Start and end with the same letter

Anchors and a backreference together describe the shape of a word:

Matches6/6 as expected
/^(.).*\1$/

Should match4/4

  • level
  • radar
  • stats
  • noon

Should not2/2

  • hello
  • regex
Try it in the Playground
The first letter is captured, .* skips the middle, and \1$ requires the same letter at the very end.

04Five-letter palindromes

With two groups you can mirror a word. Capture the first two letters, allow any middle letter, then require them back in reverse order:

Matches6/6 as expected
/^(.)(.).\2\1$/

Should match4/4

  • level
  • radar
  • kayak
  • refer

Should not2/2

  • hello
  • lever
Try it in the Playground
Group 1 must come back last and group 2 second to last, so the word reads the same both ways.

lever is close: it starts with le, but ends with er, not el.

05Matching quotes that pair up

A backreference can make sure a closing quote matches the opening one. (["']) captures either quote mark, and \1 closes with the same one:

Matches2/2 as expected
/(["']).*?\1/
  • He said "it's fine"
  • 'single' and "double"
Try it in the Playground
The apostrophe in it's doesn't end the first match, because the string was opened with a double quote.

06Named groups

Numbers get hard to follow in a long pattern. Most engines let you name a group and refer to it by name:

Pattern14 chars
/(?<ch>.)\k<ch>/
Try it in the Playground
The same doubled-letter check as (.)\1, with the group named "ch".

The syntax differs between languages. JavaScript, .NET and PCRE use (?<name>…) and \k<name>. Python's built-in re module uses (?P<name>…) and (?P=name).

07Backreferences in replacements

Captured groups are just as useful when you replace text. In most editors and languages you can put the groups back in a new order: search for (\w+), (\w+) and replace with $2 $1 (JavaScript, VS Code) or \2 \1 (Python, sed) to turn Lovelace, Ada into Ada Lovelace.

08The one place they don't work: inside [ ]

It's tempting to write (.)[^\1] for "a character followed by a different one". It doesn't work. Inside a character class, \1 isn't a backreference. In JavaScript it's read as an escaped character code, so the class means "anything except character 1":

Matches2/2 as expected
Both lines match. [^\1] doesn't compare against the captured letter, so "aa" gets through.

To say "not the same character", use a negative lookahead: (.)(?!\1).. (More on that in our lookahead and lookbehind guide.)

09Try one

On this board, every monster has two different doubled letters, like the ff and ee in coffee. Every innocent has only one:

Live huntpar 12

Catch the words with two doubled letters.

Targets · 0/5 caught

  • coffeetarget
  • balloontarget
  • bookkeepertarget
  • committeetarget
  • mississippitarget

Innocents · 0 hit

  • bookinnocent
  • letterinnocent
  • appleinnocent
  • grassinnocent
  • helloinnocent

Type a regex — the board updates as you go.

Try it in the Playground
Like this? A new one drops every day.Play today’s hunt

10Quick reference

  • ( … ) captures. Groups are numbered by their opening parenthesis.
  • \1, \2 … match the same text the group captured, not the same pattern.
  • (?<name>…) with \k<name> (JS, .NET, PCRE), or (?P<name>…) with (?P=name) (Python).
  • In replacements: $1 (JavaScript) or \1 (Python, sed).
  • \1 inside [ ] is not a backreference.

11Keep practising