Regex replace tester

Try a pattern and a replacement template on your own text. The page shows the result, checks it against the browser's own replace, and lists for every match which part of the template produced which text.

Runs in your browser with JavaScript's own RegExp and JavaScript replacement rules. Nothing is sent anywhere.

Flags

Special in the replacement: $$ $& $` $' $1–$99 $<name>.

Result

 

How each match was replaced

How to use

  1. Enter the pattern (no slashes) and choose flags. Without the g flag only the first match is replaced.
  2. Enter the replacement. Use $1 to $99 for numbered groups, $<name> for named groups, $& for the whole match, $` for the text before it, $' for the text after it, and $$ for a literal dollar sign.
  3. Paste the text. The result updates as you type, and the line under it says whether the browser's own replace() agrees.
  4. Open How each match was replaced to see the template cut into parts and what each part inserted, including the cases where a reference stays literal.

Worked examples

Each output below was worked out by hand from the ECMAScript GetSubstitution rules before it was compared with the browser, and the automated tests repeat the comparison.

Swap two words

Pattern /(\w+) (\w+)/, replacement $2 $1, text John Smith.

Result: Smith John. $1 is "John" and $2 is "Smith", so the template $2 $1 produces "Smith John".

Reformat a date with named groups

Pattern /(?<y>[0-9]{4})-(?<m>[0-9]{2})-(?<d>[0-9]{2})/g, replacement $<d>/$<m>/$<y>, text From 2026-10-02 to 2026-10-09..

Result: From 02/10/2026 to 09/10/2026.. Each date is rewritten as day/month/year by naming the groups; the surrounding text is untouched.

Wrap every match with $&

Pattern /[0-9]+/g, replacement [$&], text a1 b22 c333.

Result: a[1] b[22] c[333]. $& inserts the whole match, so "1", "22" and "333" each get square brackets.

Text before and after the match

Pattern /b/, replacement [$`|$'], text abc.

Result: a[a|c]c. The match is "b". $` is the text before it ("a") and $' is the text after it ("c"), so "b" becomes "[a|c]" and the unmatched "a" and "c" stay: "a[a|c]c".

A literal dollar sign and a group that does not exist

Pattern /(a)/g, replacement $$$1$2, text a-a.

Result: $a$2-$a$2. $$ is one literal dollar, $1 is "a", and $2 stays as the text "$2" because the pattern has only one group.

Two digits that are not a group

Pattern /(a)/, replacement $10, text abc.

Result: a0bc. There is no group 10, so JavaScript reads $1 followed by a literal 0: the match "a" becomes "a" + "0".

A group that did not take part

Pattern /(a)|(b)/, replacement [$1|$2], text b.

Result: [|b]. Only the second alternative matched, so $1 is empty and $2 is "b".

$<name> in a pattern with no named groups

Pattern /(a)/, replacement $<x>, text a.

Result: $<x>. The pattern has no named groups, so $<x> is left as plain text.

Empty matches

Pattern /x*/g, replacement -, text abxd.

Result: -a-b--d-. x* matches five times (see the tester): empty at 0 and 1, "x" at 2, empty at 3 and empty at 4. Each is replaced by "-" and the letters between are kept: -a-b--d-.

How the other flavors write the same idea

These are documentation notes only; none of them is executed on this site.

Replacement syntax in other regex flavors
FlavorNumbered groupNamed groupWhole matchLiteral dollar or backslash
JavaScript (executed)$1$<name>$&$$
PCRE2 pcre2_substitute (notes only)$1 or ${1}$name, ${name}, and the JavaScript form $<name>$0 or $&$$; backslash is literal unless the extended option is set
Python re.sub (notes only)\1 or \g<1>\g<name>\g<0>Backslash escapes are processed; unknown escapes of an ASCII letter are errors
Java appendReplacement (notes only)$1${name}$0: the javadoc says group zero denotes the entire pattern\$ for a dollar; a backslash escapes the next character
Go Regexp.Expand (executed engine, template not run here)$1 or ${1}$name or ${name}No whole-match shorthand is documented. A numeric name refers to the submatch with that index; the page does not say what index 0 means in a template, so treat $0 as unclear.$$
RE2 Rewrite (notes only)\1 to \9Not documented in the header\0Backslash-escaped
  • PCRE2. The API documentation lists $$, $n or ${n}, $<name>, $0 or $&, $`, $', $_ (the whole input) and $+, and says that dollar is the only escape character unless PCRE2_SUBSTITUTE_EXTENDED is set, which adds backslash escapes and the Python form \g<n>. By default, inserting an unset group is an error unless an option says to treat it as empty; in JavaScript it is simply empty.
  • Python. The documentation says unmatched groups are replaced with an empty string (since 3.5) and that \g<2>0 is how to write group 2 followed by a zero, because \20 would be group 20. It gives sub('x*', '-', 'abxd') as '-a-b--d-'.
  • Java. The Matcher documentation says that for $g the first digit is always part of the group reference and later digits are added only if they form a legal group reference, which is similar in spirit to JavaScript's two-digit rule, and that a literal dollar is written \$.
  • Go. The documentation says that in the $name form the name is "as long as possible": $1x means ${1x}, not ${1}x. That is the opposite of what many people expect, and a reference to a missing group is replaced with nothing.
  • RE2. The C++ header describes rewrite strings with backslash-escaped digits \1 to \9 and \0 for the whole match.

Limits & gotchas

  • Only JavaScript replacement is executed. The table for the other flavors comes from their documentation and is not run. In particular this page cannot show you how Python or Java would handle a given template.
  • Function replacers are not supported. JavaScript's replace() also accepts a function; this page covers string templates only.
  • Group names are read from the pattern. If the pattern has named groups, $<name> works; if it has none, $< stays literal, exactly as the specification says.
  • Matches are capped. The page replaces up to 10,000 matches and describes the first 20 in detail.
  • A time limit applies. A pattern that backtracks catastrophically is stopped after the chosen limit, and the Worker is restarted. See the backtracking page.

FAQ

What does $& insert, and what is the difference between $& and $1?

$& inserts the whole matched substring. $1 inserts only what the first capturing group matched. With the pattern (\d+)px on "12px", $& is "12px" and $1 is "12".

Why did my $10 turn into the first group followed by a zero?

In JavaScript, $nn is read as a two-digit group number only if the pattern has at least that many groups. Otherwise the replacement uses $n followed by the second digit as ordinary text. To be unambiguous with many groups, use named groups and $<name>.

Is the replacement run through the browser or re-implemented?

Both. The page runs your pattern with the browser's RegExp in a Web Worker, applies the replacement template with its own implementation of the ECMAScript GetSubstitution algorithm so it can explain each piece, and then compares the result with the browser's own String.prototype.replace. If the two ever differ, the page says so.

Can I test Python, Java, Go or PCRE2 replacement syntax here?

No. Only the JavaScript replacement is executed. The notes below the tool summarise how those languages write backreferences in a replacement, from their documentation, and are labelled "notes only, not executed".

Why does replacing x* give an extra dash?

Because x* can match the empty string. In "abxd" the matches are empty at 0 and 1, "x" at 2 to 3, empty at 3 and empty at 4, so replacing each with a dash gives -a-b--d-. Python 3.7 and later documents the same result; Go gives -a-b-d- because it skips an empty match that touches the previous match.

Sources

  1. ECMA-262: GetSubstitution (22.1.3.19.1) Used for: The exact algorithm for $$, $`, $&, $', $n, $nn and $<name>, including the two-digit fallback and the no-named-groups rule.
  2. MDN: String.prototype.replace() Used for: Replacement patterns $$ $& $` $' $n $<Name> and their meaning.
  3. MDN: Named capturing group: (?<name>...) Used for: Names must be unique within a pattern, except in different alternatives; groups object; unmatched named group is undefined.
  4. MDN: Capturing group: (...) Used for: Numbering by opening parenthesis, undefined for unmatched groups, last-iteration capture rule.
  5. PCRE2: pcre2api Used for: Match limit (PCRE2_ERROR_MATCHLIMIT), default newline, DOLLAR_ENDONLY, pcre2_substitute replacement syntax ($1, ${1}, $<name>, $0 or $&).
  6. Python docs: re: Regular expression operations (3.13) Used for: Syntax, (?P<name>), atomic groups and possessive quantifiers (3.11+), fixed-length lookbehind, Unicode \d \s \w, $ before trailing newline, \A \Z, re.sub replacement syntax, inline flags at start only (3.11+).
  7. Oracle (Java SE 21): java.util.regex.Matcher: appendReplacement Used for: Replacement syntax $g, ${name}, backslash escapes.
  8. Go: regexp package Used for: Linear-time guarantee, leftmost-first semantics, Expand template syntax ($1, ${name}, $name longest-name rule).
  9. Google RE2: re2.h (rewrite syntax) Used for: Rewrite strings use backslash-escaped digits \1 to \9 and \0.
  10. MDN: Worker: terminate() Used for: terminate() stops a Worker immediately without letting it finish.

Every document above was opened and read on 2026-10-02. Documentation changes; if a page here disagrees with the current docs, trust the docs and tell us.