testthisregex.com Runs in your browser
Find → replace

Regex find and replace, online

Write a pattern and a replacement, and read the rewritten text back live. The replacement understands $1, $<name>, $&, $` and $'.

Regular expression find and replace

JavaScript syntax. Write the pattern only — no surrounding slashes. Just matching, not replacing? Use the regex tester.

$1$n insert a group, $<name> a named group, $& the whole match, $$ a literal dollar. This is JavaScript, so it is $1, never \1.

Flags

g — Find every match, not just the first. i — Treat upper and lower case as equivalent. m — ^ and $ match at every line break. s — Let . match newlines too. u — Enable full unicode escapes and properties.

/(?:)/g

Write a pattern and a replacement to rewrite the text.
Result
 

The replacement vocabulary

A regex replacement is not another pattern — it is a template, and every special sequence in it starts with a dollar sign. These are the ones JavaScript's String.replace understands, which is exactly the set this page accepts:

TokenInserts
$1$99The text captured by that numbered group. $1 is the first (...) in the pattern.
$<name>The text captured by a named group written (?<name>...).
$&The whole matched substring, groups or not.
$`Everything in the subject before the match.
$'Everything in the subject after the match.
$$A single literal dollar sign.

A reference to a group that does not exist — $3 when the pattern has two groups, or $<day> when nothing is named day — is reported as an error here. Plain String.replace would quietly leave it in the output as literal text, which is a subtle way to ship a wrong string, so this page refuses it instead.

The one that trips everyone up: \1 versus $1

If you learned regular expressions in sed, Perl, Vim, or almost any PCRE-based tool, a backreference in the replacement is \1. In JavaScript it is $1. This is the single most common find-and-replace mistake, because the pattern side of both flavours looks nearly identical — it is only the replacement that diverges. Type \1 here and you get the literal characters backslash-one in your output, not the captured group.

The confusion runs the other way too: inside the pattern, JavaScript does use \1 as a backreference — (\w)\1 matches a doubled letter. So the same tool wants \1 in the pattern and $1 in the replacement. Keep the rule simple: backslash to match a repeat, dollar to write a capture.

Greedy and lazy change what gets replaced

Greediness is a matching property, but it decides the shape of every replacement, because a replacement can only substitute what a match actually covered. Quantifiers are greedy by default: <.+> against <a><b> matches the entire string, so replacing it with [$&] yields one bracketed blob rather than two tags. Add a ? to make the quantifier lazy — <.+?> stops at the first > — and with the global flag the replacement fires once per tag. When a find-and-replace does too much or too little, greediness is the first thing to check.

Why it will not freeze the tab

The substitution runs on the page's main thread, so a pathological pattern is a frozen tab rather than a slow one. A pattern like (a+)+$ against a long line that does not match backtracks catastrophically — the engine tries an exponential number of ways to split the string before giving up. Replacing is therefore capped at 1,000 matches and 250 milliseconds; hit either and the count line says so, and any text past the cap is left exactly as it was rather than partly rewritten. The regex tester applies the same two ceilings when you are only matching.

Common questions

Why doesn't \1 work in the replacement?

Because this is JavaScript, and JavaScript names a captured group in a replacement with $1, not \1. The backslash form is what sed, Perl, and most PCRE-based tools use, which is why people reach for it out of habit. Here \1 is passed through as the literal two characters backslash-one; write $1 for the first group, $2 for the second, and so on.

How do I reuse a named group in the replacement?

With $<name>, matching the (?<name>...) syntax you used to capture it. So a pattern of (?<year>\d{4})-(?<month>\d{2}) with a replacement of $<month>/$<year> swaps the two. A named group can still be reached by its position too — it counts in the numbering — so $1 and $<year> refer to the same text when year is the first group.

What do $&, $` and $' mean?

They are the whole match and the text around it. $& is the entire matched substring, $` (backtick) is everything before the match, and $' (apostrophe) is everything after it. They are the pieces String.replace exposes beyond the numbered groups, useful for wrapping a match — a replacement of [$&] brackets whatever matched without needing a capture group around the pattern.

Why did my replacement swallow more text than I expected?

Quantifiers are greedy: <.+> against <a> and <b> matches from the first < to the last >, so replacing it with one thing eats both tags and the words between them. Add a ? to make the quantifier lazy — <.+?> stops at the first > — and the replacement runs once per tag instead of once for the whole line. Greediness changes what each match covers, which is exactly what the replacement then substitutes.

Why did replacing stop before the end of my text?

Replacing is capped at 1,000 matches and 250 milliseconds, and the count line says so when a cap is hit. Some patterns backtrack catastrophically — nested quantifiers such as (a+)+ against a long non-matching string are the classic case — and because this runs on the page's main thread, an uncapped run would freeze the tab rather than merely be slow. Text past the cap is left untouched rather than half-processed.

Is my text uploaded anywhere?

No. The pattern, the replacement, and the subject all stay in your browser, and the substitution runs locally with the same engine that powers String.replace. Nothing is sent to a server, logged, or stored, and the page keeps working offline once loaded.