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 calculator
- 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.
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.
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.