Regex Portability Checker
Paste a regular expression — bare, or in JS's "/pattern/flags" form — and see exactly which parts would break, or silently behave differently, if the same pattern ran under Python's `re` module or a PCRE-family engine (PHP, Perl), and why.
Processed locally in your browser. Your file is never uploaded.
How to use this tool
- Paste a regex pattern, either bare ("\\d{4}-\\d{2}") or delimited ("/\\d{4}-\\d{2}/g") — nothing leaves your browser.
- Select "Check pattern".
- Review each flagged construct: whether it's an outright syntax error elsewhere, a silent behavior change, or a one-way compatibility note.
- Use the suggested rewrite where one is offered — some constructs (possessive quantifiers, atomic groups, recursion) have no simple mechanical JS equivalent, and those are explained instead of guessed at.
Assumptions
- This is static text scanning of the pattern source, not a regex engine — it never executes the pattern against sample text, and it doesn't parse the full regex grammar (character classes, nested groups, escaping edge cases beyond what each rule specifically targets).
- Comparisons are limited to three ecosystems: JavaScript (ECMAScript) RegExp as the home context, Python's `re` module, and the PCRE family (which PHP's `preg_*` functions and Perl's regex both follow closely).
- Only well-documented, specification-level divergences are flagged — obscure engine-specific quirks and version-specific bugs are out of scope.
Sources & reference data
Methodology
The pattern body (with any "/pattern/flags" delimiters stripped) is scanned for eight specific constructs known to cause cross-language regex portability problems: Python-only named-group and named-backreference syntax, possessive quantifiers, atomic groups, the \A/\Z/\z anchors, PCRE recursive-pattern references, inline mid-pattern flags, and the ASCII-vs-Unicode default for \d/\w/\s. Each is checked with a narrow, targeted pattern match — not a general-purpose regex parser — matching how every other portability checker in this toolset works. A rewrite is only ever offered when it is mechanically, unambiguously safe.
Worked example
\A and \Z anchors
Inputs: /\Afoo.*bar\Z/
Result: JavaScript has no \A or \Z anchor at all — it silently reads \A as a literal "A" and \Z as a literal "Z", so the pattern matches something completely different rather than failing to compile. Flagged as an error precisely because it fails silently, not loudly.
Python-style named group
Inputs: (?P<year>\d{4})
Result: "(?P<year>...)" is a SyntaxError in JavaScript, which requires "(?<year>...)" without the "P". Safely rewritten by dropping the "P" — PCRE and .NET both also accept the plain form.
Possessive quantifier and atomic group
Inputs: (?>a++)b
Result: Both "(?>...)" (atomic group) and "a++" (possessive quantifier) are PCRE/Java features with no JavaScript equivalent syntax at all. Both are flagged as errors with no automatic rewrite, since an equivalent effect in JS requires restructuring the pattern with a capturing lookahead, not a text substitution.
A Python-style start anchor
Inputs: /\Afoo/
Result: Python and some other engines use `\A` for the absolute start of the string. JavaScript has no `\A` anchor: in a JavaScript pattern, the escape is not a start anchor and may be treated as an identity escape, matching `A`. The checker spots this construct in pattern text; it does not execute it against sample strings.
Practical guidance
- Never rely on \A or \Z/\z if the same pattern might run in JavaScript — use "^"/"$" with the "m" flag deliberately off, and double-check the exact trailing-newline behavior you need.
- If a pattern needs to run under both JavaScript and Python, use "(?P<name>...)" — Python requires it, and PCRE/.NET both also accept it, so it is the more portable of the two named-group spellings even though plain JS wants "(?<name>...)".
- Treat possessive quantifiers, atomic groups and recursive patterns as a sign the pattern needs restructuring (or a real parser) before it can run in JavaScript at all — there is no drop-in replacement syntax for any of them.
Common mistakes
- Assuming a pattern that compiles without error in JS is behaviorally equivalent to the Python/PCRE version it was ported from — \A/\Z and the \d/\w/\s Unicode default both compile fine while matching different things.
- Treating "(?<name>...)" as universally portable — it's valid in JS, PCRE and .NET, but Python's `re` module rejects it outright without the "P".
FAQs
Why is \A/\Z treated as more dangerous than the possessive-quantifier or atomic-group cases?
Possessive quantifiers and atomic groups are SyntaxErrors (or effectively so) in JavaScript — the mistake is loud and immediate. \A and \Z compile successfully and just quietly match the literal letters "A"/"Z" instead of anchoring — the mistake is invisible until the pattern misbehaves on real input.
Why does this tool suggest "(?<name>...)" for JS but flag it as a warning for Python, instead of just picking one?
Which spelling is "correct" depends entirely on which engine the pattern needs to run in — JS/PCRE/.NET want the plain form, Python requires the "P". Since this tool can't know which target actually matters to you, it reports both directions and only force-rewrites the direction that's unambiguously invalid in JS specifically (Python's "(?P<name>...)" being pasted somewhere JS will read it).
Can this tool fix a possessive quantifier or atomic group automatically?
No. An equivalent effect in JavaScript generally requires an atomic-group emulation via a capturing lookahead ("(?=(pattern))\\1"), which changes the structure of the pattern, not just its text — that's a judgment call for whoever owns the pattern, not something this tool will guess at.
Last reviewed: 2026-09-25
This is a narrow, construct-by-construct text scanner, not a regex parser or engine: it recognizes eight specific well-documented portability pitfalls and nothing else, so unusual engine-specific extensions, nested-group edge cases, and any actual matching behavior are out of scope. It never executes the pattern against sample input.
Theme and tool preferences, along with saved and recently used lists, are stored only in this browser.