\1: backreferences that match what a group captured
\1 matches the same characters that capture group one matched earlier in the same attempt. It repeats the captured text, not the pattern, which is what makes doubled word detection possible.
At a glance
- Syntax
- \1 through \9 and beyond, by group number
- Matches
- the exact text the group captured, not the pattern
- Unmatched group
- a reference to a group that did not participate matches the empty string
- Inside a character class
- [\1] is not a backreference, it is the character U+0001
- In a replacement string
- use $1, because \1 there is literal text
- Case
- sensitive unless the i flag is set
In detail
The distinction that makes backreferences useful is that they repeat the captured text rather than the pattern. /(\w+) \1/ finds a doubled word because the second half must be the same word, whereas /(\w+) \w+/ would match any two words at all. That is a claim about the input that no amount of ordinary pattern syntax can express.
The other everyday use is matching a delimiter with itself. /(["']).*?\1/ matches a single quoted or double quoted string and insists that the closing quote is the same character as the opening one, which a character class on both ends cannot do. The same trick handles matched brackets of one level and repeated separators.
Two spellings catch people out. Inside a character class the escape is not a backreference at all: [\1] is a legacy octal escape meaning the character U+0001, so a class written that way matches a control character and nothing else. And in a replacement string the token is $1, because backslash escapes there are just characters.
A reference to a group that never participated succeeds rather than failing, by matching the empty string. That is defensible and occasionally surprising: a backreference inside an alternation whose group lives in the other branch will quietly match nothing at all rather than causing the attempt to fail.
Examples
"the the cat".match(/\b(\w+)\s+\1\b/)[0]; // "the the"
const s = 'He said "hi" and \'bye\'';
s.match(/(["']).*?\1/)[0]; // '"hi"'"ab".replace(/(a)(b)/, "$2$1"); // "ba"
"ab".replace(/(a)(b)/, "\\2\\1"); // "\\2\\1", literal text
/(a)[\1]/.test("aa"); // false, [\1] is the character U+0001Things that catch people out
- In a replacement string \1 is literal text and $1 is the group. Mixing them up produces output containing backslashes rather than the captured value.
- [\1] inside a character class is the control character U+0001, not a backreference, so a class written that way silently matches nothing you intended.
- A backreference to a group that did not participate matches the empty string instead of failing, which can make an alternation succeed on input it should have rejected.
Try it: Regex Tester
Type a pattern and a test string, watch every match highlight as you go, read a plain English breakdown of each token, and check the numbered and named groups it captured.
Regex Tester
LOCAL · Browser-OnlyTest and debug regular expressions with live matching and highlights
Related Regex syntax
All regex syntax →\k<name>: backreferences to a named group
\k<name> repeats what a named group captured. Get the name wrong and, without the u flag, the escape quietly becomes a literal letter k.
(...) capturing groups: numbering and what comes back
How capture groups are numbered, what a group that did not participate returns, and why quantifying a group throws away everything but the last pass.
(?:...): grouping without creating a capture
A non capturing group applies quantifiers and alternation without taking a number, which is what keeps $1 pointing at the same thing after an edit.
(?=...): positive lookahead for zero width tests
A lookahead asserts what comes next without consuming it, which is how several independent rules can all be checked from the same position.
(?!...): negative lookahead for exclusion rules
A negative lookahead succeeds when the pattern inside it fails. The classic bug is a greedy quantifier that backtracks until the assertion passes.
(?<=...): positive lookbehind and where it runs
JavaScript allows variable length lookbehind, which Java does not, and matches its contents from right to left. RE2 based engines have none at all.
Tools for this
- Regex Tester Free online regex tester - test and debug regular expressions with live matching and highlights
- Regex Playground Regex playground with live match highlighting, named groups, find and replace, and shareable links