Who supports what¶
One line: Eleven constructs, handed to five engines, with the answers produced by running them — plus the three engines that answer by refusing the whole category.
Level: reference
Keywords on this page: \1 · (?<name>…) · (?=…) · (?<=…) · (?>…) · *+ · (?R) — Topics: Choosing an engine · Portability between engines
Every table on this page is generated by a program. "yes" means one thing precisely: that engine compiled that pattern. It is not a claim that the construct means the same thing everywhere — forward references is an entire lesson about a pattern that compiles in five engines and means something different in one of them.
The measured table¶
Verified output of capability_probe_sh.sh — regenerated by tools/run_examples.py, never hand-typed.
does it COMPILE? python perl node ruby java
backreference yes yes yes yes yes
named backref, \k<w> no yes yes yes yes
named backref, (?P=w) yes yes no no no
forward reference no yes yes yes yes
lookahead yes yes yes yes yes
lookbehind, fixed width yes yes yes yes yes
lookbehind, two widths no yes yes yes yes
lookbehind, variable width no yes yes no yes
atomic group yes yes no yes yes
possessive quantifier yes yes no yes yes
recursion no yes no no no
and does it MATCH 'aax' with the forward reference ^(?:\1x|(a))+$ ?
python compile error
perl yes
node yes
ruby yes
What to notice¶
Named backreferences are a spelling war. Perl accepts both; Python accepts only its own (?P=w); JavaScript and Java accept only \k<w>; Ruby accepts \k<w>. Python invented (?P<…>) and PCRE adopted it, which is why the same pattern often works in ABAP and fails in Node.
Forward references split the field cleanly. Everything but Python compiles them. Python rejects them while parsing.
Lookbehind is three separate questions, not one. Python refuses even two fixed-width branches. Ruby accepts branches of different lengths but refuses a bounded repeat. Java and JavaScript accept everything asked here.
Atomic groups and possessive quantifiers are missing only from JavaScript. Python gained both in 3.11. If you have been writing (?>…) off in Python for years, it works now — and what they do to a match is a larger change than the speed they are reached for.
The recursion row says (?R), and that is not the same question as "has recursion". Ruby has recursion and answers no here because Onigmo spells it \g<0>; the two dialects have no overlap, so each engine rejects the other's spelling entirely. PCRE2 has (?R), which means ABAP does; Python's re does not, though the third-party regex module does. Matching nested structures puts every spelling to every engine.
And this is where "yes means it compiled" earns its warning label. Two cells not in this table are silent false positives: JavaScript accepts \g<0> as an identity escape meaning the literal text g<0>, and Rust's regex accepts (?R) because R is its CRLF-mode flag, so the group sets a flag and consumes nothing. Both produce a working pattern that matches something and is not recursion, with no warning from either engine. A probe that only asks "did it compile" cannot tell the difference — which is the argument for the behaviour columns on the lesson pages.
The engines that refuse the category¶
The probe covers engines that at least have these features. Three more matter and answer differently:
| Engine | Backreferences | Lookaround | Guarantee |
|---|---|---|---|
Go regexp (RE2) |
none | none | linear in the subject, always |
Rust regex |
none | none | linear in the subject, always |
Rust fancy-regex |
yes | lookahead, fixed-width lookbehind | none — a backtrack limit instead |
This is a deliberate trade, not a gap. See what a backreference costs for the measurement.
The full picture, by family¶
Most engines are one of four lineages, and knowing the lineage predicts the answers better than memorising the table.
| Family | Members | Character |
|---|---|---|
| Perl / PCRE | Perl, PCRE2, ABAP (PCRE, 7.55+), PHP, R (perl=TRUE) |
The largest feature set: recursion, \K, atomic groups, conditionals. Backtracking. |
| Onigmo / Java / .NET | Ruby, Java, C#, JavaScript | Perl-like, each missing a different corner. JavaScript is the smallest; .NET adds variable lookbehind and named-group stacks. |
Python re |
Python | Perl-like, strict about lookbehind width and forward references. The third-party regex module relaxes both. |
| Automata | Go regexp, Rust regex, RE2, grep -E |
No backreferences, no lookaround, linear time. |
| POSIX | grep, sed, awk, C <regex.h> |
BRE has \1 by requirement; ERE has it only by common extension. Leftmost-longest matching, which differs from everyone else. |
Where ABAP sits¶
ABAP is in the Perl/PCRE family, which is the single most useful thing to know about it:
PCREaddition (7.55 and later) — the PCRE2 library in the kernel. Backreferences\1, named groups, forward references, lookaround with PCRE2's width rules,\K, atomic groups, possessive quantifiers, recursion. Replacement uses$1.REGEXaddition (older, obsolete since 7.55) — a POSIX-flavoured engine. Still compiles, still runs, and does not agree with PCRE at the edges. Moving a pattern fromREGEXtoPCREdeserves a test.CL_ABAP_REGEXwithCREATE_PCRE, andCL_ABAP_MATCHER, are the object-oriented way in when you want to compile once and match repeatedly.
A pattern that works in Perl, in pcre2grep, or in a PCRE-mode online tester is the best available prediction of what ABAP will do. A pattern that works in Python is not.
How this page stays honest¶
The table is regenerated by tools/run_examples.py, which runs capability_probe_sh.sh and pastes its output. Adding an engine means adding a probe_* function; adding a construct means adding one line to the pattern list. Nothing here is transcribed from a documentation page, which is why the named backref rows are split by spelling — the first draft asked Python for \k<w>, got "no", and would have published a table saying Python has no named backreferences at all.
See also¶
- Backreferences — the chapter these features come from.
- Lookahead and lookbehind — the width rules in detail.
- Resources — where each engine documents itself.