Skip to content

(?R), (?1), (?&name), \g<0> — call the pattern again

One line: A subroutine call re-runs a group's pattern at this position (a backreference re-matches its text), and (?R) re-runs the whole pattern, which is what it takes to match balanced parentheses; Perl and PCRE2 spell it (?R) / (?1) / (?&name), Ruby spells it \g<0> / \g<1> / \g<name>, the two dialects have no overlap, and two other engines accept one of the spellings while meaning something else.

Level: reference · one construct, eight engines — the lesson has the depth

What it means

Construct Perl / PCRE2 / ABAP Ruby (Onigmo)
Recurse into the whole pattern (?R), (?0) \g<0>
Call group 1's pattern (?1) \g<1>
Call a named group's pattern (?&name), (?P>name) \g<name>
Relative call (?-1), (?+1) \g<-1>, \g<+1>

Python re, JavaScript, Java, Go and Rust's regex have none of this. fancy-regex has none of it either. The Python third-party regex module has the PCRE spelling.

Measured

Verified output of kw_recursion_and_subroutine_calls_sh.sh — regenerated by tools/run_examples.py, never hand-typed.

construct               python  perl     node  ruby     java  go  rust  fancy
(?R) whole pattern      -       (a(b)c)  -     -        -     -   (b)   -
(?1) group one          -       (a(b)c)  -     -        -     -   -     -
(?&name)                -       (a(b)c)  -     -        -     -   -     -
\g<0> Ruby spelling     -       -        (b)   (a(b)c)  -     -   -     -
\g<name> Ruby spelling  -       -        (b)   (a(b)c)  -     -   -     -
subroutine vs backref   -       12-34    -     -        -     -   -     -
backref for comparison  no      no       no    no       no    -   -     no

Reading the table

  • Rows 1–3, the PCRE dialect. (?R), (?1) and (?&name) each match the whole of (a(b)c) in Perl. Ruby, Python, JavaScript, Java, Go and fancy-regex refuse all three.
  • Row 1, Rust. regex did not refuse (?R). R is its CRLF-mode flag, so (?R) is a flag group that consumes nothing, the pattern collapses to one level of parentheses, and the first match is the inner (b). It compiles, it matches, it is not recursion.
  • Rows 4–5, the Ruby dialect. \g<0> and \g<name> match the whole nested subject in Ruby, and are refused by Perl — the dialects do not overlap in either direction. JavaScript did not refuse them: \g is an identity escape, so \g<0> is the literal text g<0> and the alternative [^()]|g<0> matches (b). The library's engines table once said recursion was Perl's alone, because its probe only asked for (?R).
  • Rows 6–7, call versus backreference. (\d\d)-(?1) matches 12-34 in Perl: the second \d\d is the pattern again. (\d\d)-\1 matches nothing, in every engine that has backreferences: \1 wants the text 12 again. That line — pattern versus text — is the whole difference between this page and backreference.

The trap

Two engines compiling one of the spellings and meaning something else: Rust for (?R), JavaScript for \g<…>. A compile-only probe credits both with recursion. The lesson's own probe asked "does it match the nested subject" for exactly this reason.

The judgement call, from the lesson: nested structure usually wants a parser. A dozen lines of depth-counting in the host language handles unbalanced input and unlimited depth, is portable to every engine on this page, and is what Go and Rust force on you anyway. The recursive pattern is a real capability where it exists — and on hostile input it is catastrophic backtracking again.

Where it is measured in depth

  • Matching nested structures — six spellings × five engines, the anchor trap, depth to 1000, the counter in Python, and the ABAP source.

See also

  • Backreference — text, not pattern.
  • Conditional — (?(DEFINE)…) for naming the sub-patterns a call refers to; (?(R)…) for "am I inside a recursion".
  • Forward references — the page that first draws the four-names distinction.