Regex Tester
Test a pattern against sample text with live match highlighting.
"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.
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.
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.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.(?<=a|bc) is fine. Java's rule is undocumented and stranger than either camp assumes. Python, Go and Rust do not allow it.(?>…) 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.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).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.^ 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.