skip to content

What is a backreference in a Java regex, and what is a common use for one?

level: seniorimportance: should knowfreq 52%

answer

  1. \1 / \k<name> match the captured TEXT, not the pattern
  2. classic: \b(\w+)\s+\1\b finds doubled words
  3. pattern uses \1; replacement uses $1
  4. backreferences → non-regular → ReDoS risk

basics

~10 s

A backreference like \1 matches the same text that an earlier capturing group already matched (not the pattern again, the actual text). A common use is finding doubled words, e.g. \b(\w+)\s+\1\b matches 'the the'.

solid answer

~40 s

A backreference makes part of a pattern require the *same literal text* that an earlier capturing group matched. Numerically you write \1, \2, ... referring to group 1, group 2, etc.; for a named group you write \k<name>. The key point is that it matches the captured *text*, not re-runs the sub-pattern: if group 1 captured 'abc', then \1 only matches another 'abc' at that position. Classic uses are detecting repeated words (\b(\w+)\s+\1\b), ensuring a quoted string's closing quote matches its opening quote ((['\"]).*?\1), or matching paired HTML-ish tags. Note that backreferences make the language non-regular, can cause catastrophic backtracking on adversarial input, and \10 is ambiguous (group 10 if it exists, else group 1 + literal 0) — Java resolves it greedily to the largest valid group number.

code

java · 8 lines
java
Pattern dup = Pattern.compile("\\b(\\w+)\\s+\\1\\b");
Matcher m = dup.matcher("the the cat");
if (m.find()) {
    System.out.println(m.group()); // the the
    System.out.println(m.group(1)); // the
}
// Named backreference: matching quotes
boolean ok = Pattern.matches("(?<q>['\"]).*?\\k<q>", "\"hi\""); // true

go deeper

for a junior

Recognizes \1 refers back to a captured group and can name the doubled-word example.

for a middle

Explains it matches captured text not the pattern, and distinguishes \1 (pattern) from $1 (replacement).

for a senior

Discusses named backreferences, the non-regular implications, multi-digit ambiguity, and basic ReDoS awareness.

for a principal

Weighs backreference use against ReDoS exposure on untrusted input, recommends atomic/possessive mitigations, and knows engine-class trade-offs (backtracking NFA vs DFA).

## Foundations recap A **capturing group** `( ... )` records the exact substring it matched and gives it a number (or a name). Normally you read that captured text *after* the match with `group(n)`. A **backreference** lets you use that captured text *during* the same match. ## What a backreference is A **backreference** is a token inside the pattern that says: "match the same literal characters that capturing group N already captured." Syntax: - `\1`, `\2`, ... `\9` — by number. - `\k<name>` — by name (for named groups). Crucially, it matches the **text**, not the pattern. If group 1 is `(\w+)` and it captured `cat`, then `\1` later in the string matches only the literal `cat` at that point — not any word. ## A worked example: doubled words ``` \b(\w+)\s+\1\b ``` - `\b` is a word boundary. - `(\w+)` captures a word into group 1. - `\s+` matches the spaces between. - `\1` requires the *same* word again. So it matches `the the` or `is is`, but not `the cat`. ## A worked example: matching the same quote ``` (['\"]).*?\1 ``` Group 1 captures whichever quote character appears first (`'` or `"`). `.*?` lazily matches the contents, and `\1` requires the **same** quote to close. This correctly handles both `'hi'` and `"hi"` but rejects `'hi"` (mismatched quotes). ## Named backreferences With a named group `(?<q>['\"])`, the backreference is `\k<q>`. Equivalent behavior, clearer code. ## Important subtleties 1. **Non-regular language.** Backreferences let a regex require equality of two arbitrary substrings, which a classical (finite-automaton) regular expression cannot. Java's engine is a backtracking NFA, so it supports this — at the cost of potentially exponential time. 2. **Catastrophic backtracking.** Patterns combining backreferences with ambiguous quantifiers can blow up on crafted input, a denial-of-service risk (ReDoS). Be cautious with untrusted input; consider possessive quantifiers or atomic groups. 3. **Multi-digit ambiguity.** `\10` could mean "group 10" or "group 1 followed by literal 0." Java reads as many digits as form a *valid existing* group number, preferring the larger; so `\10` is group 10 only if at least 10 groups exist, otherwise group 1 then `0`. 4. **Non-participating group.** If the referenced group didn't participate in the match (captured nothing, value null), the backreference typically fails to match. 5. **Backreference vs replacement reference.** Inside the *pattern* you use `\1` / `\k<name>`. Inside a *replacement string* (for `replaceAll`) you use `$1` / `${name}`. They look similar but live in different places — a common confusion. ## When to use Backreferences are the right tool whenever the pattern must enforce that two parts of the input are *identical* — repeated words, balanced quote/delimiter characters, or simple paired tags. When you don't need that equality constraint, avoid them, both for clarity and to sidestep backtracking pitfalls.

  • What is the difference between \1 and $1 in Java regex code?
    \1 is a backreference used inside the pattern to match earlier captured text. $1 is a reference used inside a replacement string (replaceAll/appendReplacement) to insert captured text into the output.
  • Why can backreferences be a performance/security concern?
    They make the regex non-regular and rely on backtracking; with ambiguous quantifiers and crafted input they can cause catastrophic backtracking (ReDoS), an exponential-time denial of service.

A backreference is like saying 'and the rest of the sentence must rhyme with the word I just said' — it constrains later text to echo earlier captured text, not just any matching shape.

saying these in an interview costs you the question

  • Thinking \1 re-matches the group's pattern instead of its captured text
  • Using $1 inside the pattern or \1 inside the replacement string
  • Ignoring ReDoS risk on untrusted input
  • Assuming \10 always means group 10 regardless of how many groups exist

context