Regex Flavor & Portability Checker

"Regex" is not one language. A pattern that works in PHP can be rejected outright by Go, silently mean something different in Ruby, and fail on a subtlety in Python that most references get wrong. This tool parses your pattern, identifies the flavor-specific constructs it uses, and tells you which of <strong>nine engines</strong> will run it — naming the exact blocker and the workaround for each. Everything runs in your browser.

Paste the pattern only — no delimiters, no flags. Nothing is uploaded.

      How to Use This Tool

      1. Paste the pattern — the expression itself, without delimiters or trailing flags.
      2. Check the detected constructs — the chips list every flavor-specific feature found, so you can confirm it read your pattern the way you meant it.
      3. Read the blocked engines first — each names the construct that stops it and, where one exists, the workaround or equivalent syntax.
      4. Then read the caveats — these run your pattern but with a behaviour difference worth knowing, such as a width restriction or a flag requirement.

      Why Regex Flavors Diverge

      Almost every regex engine in wide use is a backtracking engine descended from the same Perl lineage, which is why the basics — character classes, quantifiers, alternation, groups — look identical everywhere. The divergence starts at the features Perl kept adding: atomic groups, possessive quantifiers, recursion, conditionals, and look-around. Each engine adopted a different subset at a different time, using slightly different syntax, and the result is that portability failures cluster in exactly those constructs.

      The sharpest divide is not about features at all, though. Go's RE2 and Rust's regex crate deliberately reject the backtracking model in favour of a guarantee: matching completes in time linear in the input size, with no catastrophic-backtracking failure mode. That guarantee is incompatible with look-around and backreferences, because both require the engine to revisit input it has already consumed. So the absence of those features in Go and Rust is not a gap to be filled later — it is the price of the guarantee, paid deliberately. Every other engine on this list can be made to hang on a hostile pattern.

      The remaining trap is that engines fail differently. Go and Rust reject an unsupported construct at compile time, loudly. But JavaScript's \p{L} without the u flag compiles fine and silently matches the wrong thing; Ruby's /m means dot-matches-newline rather than multi-line, so a pattern ported from Python changes meaning without erroring; and Ruby quietly turns every unnamed group non-capturing the moment you introduce a named one. Those silent divergences cause more production bugs than the loud rejections, and they are the reason a checker is more useful than a feature table alone.

      Frequently Asked Questions

      Which regex engines have no lookahead or lookbehind at all?
      Go (RE2) and Rust (the regex crate). This is structural rather than an oversight: both guarantee matching in time linear in the input size, and look-around cannot be implemented within that guarantee. The same reasoning removes backreferences from both. If you need look-around in Rust, the fancy-regex crate adds it by giving up the linear-time property; in Go the usual answer is to restructure the pattern or filter in code after matching.
      Does Python support variable-length lookbehind?
      No — and the common description of the rule is wrong. Python's re requires the lookbehind to be strictly fixed-width, not merely bounded. So (?<=x{2,3}) is rejected even though its length is bounded to 2 or 3. The docs are explicit: the contained pattern must match strings of some fixed length, so abc and a|b are allowed but a* and a{3,4} are not. The PyPI regex module removes this restriction.
      Which engines allow variable-length lookbehind?
      JavaScript and .NET allow it without restriction — .NET because it performs full right-to-left matching, and JavaScript because the spec production is an unrestricted disjunction. PHP allows it from 8.4 (PCRE2 10.43+) but caps each branch at 255 characters and still rejects unlimited repetition. Ruby requires fixed width per top-level alternative, so (?<=a|bc) is fine. Java's rule is undocumented and stranger than either camp assumes. Python, Go and Rust do not allow it.
      Does Python have atomic groups and possessive quantifiers?
      Yes, since Python 3.11(?>…) and *+ / ++ both work. This is probably the most widely-repeated stale claim about Python regex: a great deal of writing still says Python lacks them, which was true only through 3.10. Python also supports conditionals like (?(1)yes|no), including on named groups; what stdlib re lacks is the ability to use a lookaround as the conditional test.
      Why does my \p{L} not work in JavaScript?
      Because you omitted the u or v flag — and the failure is silent rather than loud. Without the flag, /\p{L}/ does not throw; it matches the literal text p{L}. So the pattern compiles, runs, and quietly matches nothing you intended. Add u (or v, from ES2024, which also brings set operations and properties of strings).
      Does JavaScript have an x / verbose flag?
      No, and this is easy to get wrong right now. ES2025 shipped inline regular-expression modifiers, but only for i, m and s(?x:…) throws a SyntaxError. The extended-mode proposal that would add x is separate and has been at Stage 1 since 2021. Go likewise has no verbose flag: its entire flag set is i, m, s, U.
      How accurate is this checker?
      Detection is textual: it finds constructs by their syntax and maps them to a capability table verified against primary documentation on 2026-07-24. It reliably catches the constructs that make a pattern non-portable. It cannot catch a semantic difference that uses no distinctive syntax — for example, Ruby's ^ and $ are always line anchors regardless of flags, and Go's $ behaves like \z rather than \Z. A clean result means no known-unsupported construct was found, not that behaviour is identical everywhere.