The task that made me build this was boring, which is exactly why it was worth automating. A client handed me a 4,000-line export where every date was written American-style, 01/15/2024, and the system it was going into wanted ISO, 2024-01-15. A plain find-and-replace could not touch it, because there was no fixed string to search for - the dates were all different. What they shared was a shape: two digits, a slash, two digits, a slash, four digits. That is precisely the kind of thing a regular expression matches, and precisely the kind of thing a regex replacement rewrites in one pass. I pasted the file into a scratch tool, wrote one expression, and the whole export flipped format in under a second.
That is the job the free Regex Replace tool does, and this guide is the long version of how to use it well. I will cover what a regex replacement actually is, how capture group backreferences let you restructure text instead of only deleting it, what every special replacement token means, and the mistakes that trip people up. It sits next to the Regex Tester I wrote about separately - the tester tells you what a pattern matches, and this tool rewrites what it matched. If regular expressions themselves are new to you, start with the complete coding-tools guide and come back.
TL;DR: A regex replacement matches text by pattern and rewrites each match using a replacement string. Wrap the parts you want to reuse in parentheses to create numbered groups, then reference them in the replacement with
$1,$2, and so on - the pattern(\d{4})-(\d{2})-(\d{2})with replacement$3/$2/$1turns2024-01-15into15/01/2024. Turn on thegflag to replace every match, leave the replacement empty to delete matches, and use$<name>for named groups. The Regex Replace tool runs entirely in your browser and shows the replacement count live.
What is a regex replacement?
An ordinary find-and-replace works on literal text: you type the exact word you are looking for and the exact word to put in its place. It fails the moment the thing you want to change is not a fixed string but a pattern - a date in any of a hundred forms, a phone number, an HTML tag, a trailing whitespace run, a variable name that follows a convention. A regular expression describes that pattern, and a regex replacement pairs it with a template that says how each match should be rewritten.
The mechanism has two halves. The pattern is a regular expression that the engine scans your text with, finding every place the shape occurs. The replacement is a string that is substituted in for each match. In the simplest case the replacement is plain text and every match becomes the same thing - useful for normalising, say, every run of tabs and spaces into a single space. The powerful case is when the replacement refers back to parts of what was matched, so the output is built from the input rather than being a fixed constant. That is what turns a regex replacement from a blunt delete-and-retype into a genuine restructuring tool.
Under the hood, the Regex Replace tool uses the JavaScript RegExp engine and the String.prototype.replace method that every browser and Node.js ships. That matters for a practical reason: the behaviour you see in the tool is identical to the behaviour you will get if you paste the same pattern and replacement into your own JavaScript or TypeScript code. There is no separate flavour to learn and no surprise when you move from the scratch tool to production. The replacement syntax the tool accepts - $1, $&, $<name> and the rest - is the exact syntax the standard defines, documented on MDN's String.replace reference.
How do capture group backreferences work?
This is the single most useful idea in regex replacement, and it is worth slowing down for. When you put part of a pattern inside parentheses, you create a capture group. The engine remembers the text that group matched, and numbers the groups from left to right starting at one. In the replacement string, $1 means "insert whatever the first group captured," $2 the second, and so on up to $99.
The date example makes it concrete. The pattern (\d{4})-(\d{2})-(\d{2}) has three groups: the four-digit year, the two-digit month, and the two-digit day. When it matches 2024-01-15, group one holds 2024, group two holds 01, and group three holds 15. A replacement of $3/$2/$1 then assembles a new string from those pieces in a different order and with different separators, producing 15/01/2024. Nothing was deleted and retyped - the output is literally rebuilt from the captured fragments. Reorder the tokens, change the punctuation between them, wrap them in other text, and you have reformatted every date in the file with one expression.
Named groups are the same idea with readable labels. Instead of counting parentheses, you write (?<year>\d{4}) and refer to it in the replacement as $<year>. For a pattern with two or three groups the numbers are fine, but once you are juggling five or six, names make both the pattern and the replacement far easier to read and to change later. The tool supports both interchangeably, so you can mix $1 and $<name> in the same replacement if you like. When you are first assembling a pattern and are not yet sure which groups you need, the Regex Builder helps you construct it piece by piece before you bring it here to run the replacement.
What do the special replacement tokens mean?
The dollar sign is special inside a replacement string, and it introduces a small set of tokens beyond the numbered and named groups. Knowing them saves you from reaching for a more complicated pattern than you need.
$& inserts the entire matched substring. It is what you want when you are wrapping or annotating matches rather than rebuilding them - a pattern of \b\w+@\w+\.\w+\b with a replacement of <$&> puts angle brackets around every email address without you having to capture the whole thing in a group. $\`` (a backtick) inserts everything *before* the match, and $'(an apostrophe) inserts everything *after* it; these are rarely needed but occasionally exactly right. And because$is special, outputting a literal dollar sign requires doubling it:$$in the replacement produces a single$` in the output, which matters the day you are reformatting currency.
There is one deletion idiom that is worth committing to memory: an empty replacement removes every match. With the global flag on and the Replace field left blank, the tool deletes each occurrence of the pattern from the text. That is the cleanest way to strip something - all HTML tags with <[^>]+>, every trailing space with +$ in multiline mode, all non-digits from a phone number with \D. You are not replacing with a space or a placeholder; you are replacing with nothing, and the match simply vanishes.
Which flags matter for a replacement?
The flags on a regex change how it is applied, and two of them dominate everyday replacement work. The rest are situational but occasionally decisive.
The global flag, g, is the one you will toggle most. Without it, JavaScript's replace changes only the first match and leaves the rest of the text alone - this is standard String.replace behaviour and surprises people who expect a replace-all. Turn g on and every match in the text is rewritten. The tool defaults to global on, because replacing everything is what people mean nineteen times out of twenty, but the toggle is there for the times you genuinely want to touch only the first occurrence. The ignore-case flag, i, makes the pattern match regardless of letter case, so error also matches Error and ERROR - essential when you are normalising log levels or tidying inconsistent capitalisation.
The multiline flag, m, changes what the anchors ^ and $ mean: with it on, they match the start and end of each line rather than of the whole text, which is what you want when you are stripping trailing whitespace or prefixing every line. The dotAll flag, s, lets the dot match newline characters, so a pattern can span line breaks - useful for rewriting multi-line blocks. The u (unicode) and y (sticky) flags are for advanced cases: u enables correct handling of characters outside the basic plane and certain escape forms, and y anchors each match attempt to the exact position after the previous one. The comparison table below summarises when each one earns its place.
| Flag | Letter | Effect on a replacement | Typical use |
|---|---|---|---|
| Global | g |
Replace every match instead of only the first | Almost every replace-all |
| Ignore case | i |
Match regardless of letter case | Normalising log levels, tidying capitalisation |
| Multiline | m |
^ and $ anchor to each line |
Prefixing lines, stripping trailing spaces |
| DotAll | s |
The dot matches newlines too | Rewriting multi-line blocks |
| Unicode | u |
Correct handling of astral characters and \u{...} |
Emoji, non-Latin scripts |
| Sticky | y |
Match only at the current position | Tokenisers, strict sequential parsing |
When should I use regex replace instead of a plain find-and-replace?
The dividing line is simple: use a plain find-and-replace when you know the exact text, and reach for regex replace when you know the shape but not the exact text. If you are changing every 2023 to 2024, an ordinary replace is faster and safer. If you are changing every four-digit year regardless of value, only a pattern can express that.
Three families of task fall clearly on the regex side. The first is reformatting, where the content stays the same but its arrangement changes - dates, phone numbers, names written "Last, First" that you want as "First Last." Capture groups plus a reordered replacement handle all of these. The second is bulk stripping, where you delete everything matching a pattern - tags, comments, control characters, extra whitespace - by replacing with nothing. The third is conditional editing at scale, where you wrap, prefix, or annotate every occurrence of a pattern, using $& to keep the match and add to it. When the transformation you are describing to yourself contains the word "every" followed by a description rather than a literal string, you are in regex-replace territory.
There is also a workflow argument. Doing these edits in your code editor's find-and-replace works, but it edits the file in place, which means a mistake is a mistake in your real file. Running the transformation in a scratch tool first lets you see the output and the replacement count before you commit anything, then paste the verified result back. Because the Regex Replace tool runs entirely in your browser and never uploads what you paste, it is safe to use even when the text is a production log or a customer export - a point I make in full in the data-privacy guide for online tools.
What are the common mistakes with regex replace?
The most frequent one is forgetting the global flag and wondering why only the first match changed. If your replacement seems to have done almost nothing - one edit where you expected dozens - check that g is on. It is such a common trip that the tool defaults it to on, but the moment you turn it off to target a single match, remember to turn it back.
The second is a literal $1 appearing in the output where you expected captured text. That almost always means the group you are referencing does not exist - your pattern has no first set of parentheses, so there is nothing for $1 to stand in for, and the engine leaves the token as-is. The fix is to wrap the part you want to reuse in parentheses to create the group, and to count groups from the left starting at one. A related trap is miscounting when your pattern has nested or optional groups; when the numbering gets confusing, switch to named groups so the reference is unambiguous.
The third mistake is a pattern that matches more than you intended, usually because a quantifier is greedy. A pattern like <.+> meant to match one HTML tag will happily match from the first < to the last > on the line, swallowing everything between two tags. The cure is a non-greedy quantifier, <.+?>, or a more precise character class, <[^>]+>. This is exactly the situation where you verify the pattern in the Regex Tester first, watch what it highlights, and only then run the replacement - a habit the regex-tester guide walks through in detail. The replacement count shown in the tool is your other safeguard: if it reports far more or far fewer replacements than the number of things you meant to change, the pattern is wrong, not the tool.
A worked example: reformatting names and stripping noise
Let me walk through a small job end to end, because seeing the pieces work together fixes the idea better than any single rule. Suppose you have a list of contacts exported as Doe, Jane and Smith, John, one per line, and you want them as Jane Doe and John Smith.
The shape of each line is: some word characters, a comma, a space, then more word characters. As a pattern that is (\w+), (\w+), with the surname captured in group one and the given name in group two. The replacement that swaps them and drops the comma is $2 $1 - group two, a space, group one. Paste the list into the Regex Replace tool, enter that pattern and replacement, leave the global flag on, and every line flips to "First Last" at once. The replacement count tells you how many lines were touched, which you can sanity-check against the number of contacts.
Now say the same export has trailing whitespace on some lines that you also want gone. That is a second, separate replacement: pattern +$ with the multiline flag on so $ matches the end of each line, and an empty replacement so the matched spaces are deleted rather than replaced. Run it after the name swap and the file is clean. The two-pass approach - one replacement to restructure, one to strip - is typical, and because each pass shows you its output and count before you copy it out, you are never guessing whether the transformation did what you meant. When the reshaped text needs a final visual diff against the original to confirm nothing else moved, paste both versions into the Text Diff tool. For the broader kit of everyday utilities this fits into, the web developer toolkit collects the ones I reach for most.
Frequently Asked Questions
How do I find and replace with a regular expression online? Enter your pattern in the Find field without slashes, write the replacement in the Replace field, choose your flags, and paste your text. The rewritten output appears instantly and shows how many replacements ran. Everything happens in your browser, so nothing is uploaded.
How do capture group backreferences work in the replacement?
Parentheses in your pattern create numbered groups, and you reuse them in the replacement with $1, $2, and so on. For example, the pattern (\d{4})-(\d{2})-(\d{2}) with the replacement $3/$2/$1 turns 2024-01-15 into 15/01/2024. Named groups like (?
How do I replace all matches instead of just the first? Enable the g (global) flag. Without it, JavaScript replaces only the first match, exactly as the String.replace method behaves. With g enabled, every match in the text is replaced, which is what most replace-all tasks need.
How do I delete every match instead of replacing it? Leave the Replace field empty. With the global flag on, each match is removed from the text. This is the cleanest way to strip tags, whitespace runs, or unwanted characters that share a pattern.
What do the special tokens $&, backtick, and apostrophe mean in the replacement? $& inserts the entire matched substring, a backtick inserts the text before the match, and an apostrophe inserts the text after it. To output a literal dollar sign, write $$. These follow the standard JavaScript String.replace special replacement patterns.
What regex flavor does this tool use? It uses the JavaScript (ECMAScript) RegExp engine built into your browser, which is identical to the one in Node.js. Results here match how the same pattern and replacement behave in JavaScript and TypeScript. JavaScript regex differs from PCRE, Python re, and Java in some advanced features.
Why does my replacement produce a literal $1 instead of the captured text? A literal $1 in the output usually means your pattern has no first capture group, so there is nothing for $1 to reference. Wrap the part you want to reuse in parentheses to create the group, and count groups from left to right starting at 1.
Is it safe to run regex replace on sensitive data? Yes. All matching and replacing happens in JavaScript inside your browser, so no pattern, replacement, or text is sent to any server, nothing is logged, and the tool works with your connection disabled. You can safely reformat log files, personal data, or proprietary formats.
This guide accompanies the free Regex Replace tool on toolz.dev - no signup, no uploads, works offline.



