Free · Fast · Privacy-first

Regex Replace Online, Preview Substitutions Before Running Them

Running a regex replace on production data or across a large codebase without testing it first is a common source of hard-to-reverse mistakes.

Preview regex replacement output before running it on real data

🔒

Test capture group back-references in replacement strings

See the full transformed output for each match

No risk: verify in the tester before touching production files

Cost
Free forever
Sign-up
Not required
Processing
In your browser
Privacy
Files stay local
FreeNo signupWhite-label

Add this Regex Tester to your website

Drop the Regex Tester into any page — blog post, product docs, intranet, school portal — with a single line of HTML. Your visitors get the full tool, processed entirely in their browser. No backend, no uploads, no signup.

  • Files stay 100% in the visitor's browser
  • Responsive — adapts to any container width
  • Free forever, no API key needed

Embed code

<iframe
  src="https://www.fixtools.io/developer/regex-tester?embed=1"
  width="100%"
  height="780"
  frameborder="0"
  style="border:0;border-radius:16px;max-width:900px;"
  title="Regex Tester by FixTools"
  loading="lazy"
  allow="clipboard-write"
></iframe>

Attribution-friendly: a small "Powered by FixTools" link appears in the embed footer.

How Regex Replace Works and Why to Test It First

Regex find-and-replace is one of the most powerful and most dangerous text manipulation operations in a developer's toolkit. The power comes from the ability to express complex structural transformations with a compact pair of patterns: a find expression with capture groups that isolate the parts to keep, and a replacement string that reassembles those parts in a new order. The danger comes from the same compactness: a subtle error in the replacement string, a wrong group number, a missing dollar sign, or a misidentified group index, can corrupt data across hundreds or thousands of lines in a single operation. In most editors and command-line tools, undo history is limited, and for database or file system operations there may be no undo path at all. Testing the complete find-and-replace pair in an online tool before running it on real data is the most effective way to catch these errors before they become incidents.

In JavaScript, String.prototype.replace() accepts a regex as the first argument and a replacement string or function as the second. In the replacement string, $1 refers to the first capture group, $2 to the second, and $<name> to a named group. In Python re.sub(), the equivalents are \1, \2, and \g<name>. In sed, back-references use \1 and \2. The conceptual model is identical across all three tools: the matched portion of the string is replaced by the replacement string with group references substituted by the corresponding captured text. Errors arise when group indices are off by one, when groups are inside optional sections that do not participate in every match so the captured value is undefined, or when the replacement string contains a $ or \ that the engine interprets as a special character rather than as literal text.

For large-scale code transformations such as renaming function parameters, updating import paths, or reformatting date strings across an entire data file, the recommended workflow is: test the find-and-replace pair on a representative five to ten line sample in the online tester, verify that the output looks correct for every line in the sample, run the full operation on the complete dataset, and then diff the result against the original to confirm the scope of changes. The tester step catches group index errors and unintended matches before they affect thousands of lines, and the diff step after running catches any edge cases the sample did not represent.

Replacement syntax also varies meaningfully across regex flavours, and a copy-paste between tools can produce surprising failures. JavaScript replace uses $1, $2, and $<name> for group references and treats a literal $ in the replacement as needing a doubled $$ to escape. Python re.sub uses \1, \2, and \g<name>, with a literal backslash needing to be written as \\ in non-raw strings. PCRE-derived tools like Perl and PHP use $1 or \1 depending on context. The sed command uses \1 and treats unescaped & as a back-reference to the entire match. The safest rule when porting a replacement string between flavours is to write a tiny test case in the destination tool first, with a pattern that has a single capture group, and confirm the substitution output exactly matches what you expect before scaling up to the full transformation.

How to use this tool

💡

Enter your find pattern, set the replacement string using $1, $2, or $<name> for group references, and paste your test text. The tester shows the output string after replacement alongside the original.

How It Works

Step-by-step guide to regex replace online, preview substitutions before running them:

  1. 1

    Enter the find pattern

    Type or paste your regex pattern into the pattern field. Wrap the portions of the match you want to reuse in the replacement string inside capture group parentheses. For example, to reformat dates, use (\d{4})-(\d{2})-(\d{2}) to isolate year, month, and day as separate capture groups indexed 1, 2, and 3.

  2. 2

    Write the replacement string

    In the replacement field, use $1, $2, and $3 to reference numbered capture groups, or $<name> to reference named groups. Surround references with any literal characters needed for the reformatted output. For example, $3/$2/$1 reassembles a YYYY-MM-DD date capture as DD/MM/YYYY.

  3. 3

    Enable the g flag

    Enable the global flag to replace every occurrence in the test string rather than only the first one. Without the g flag, the engine stops after the first match, which is useful only when testing single-instance replacements. For bulk transformations across a file, g is almost always required.

  4. 4

    Paste your test text

    Enter representative sample text covering the range of input variations your replacement will encounter in production. Include lines where the pattern matches, lines where it does not, and any edge cases you are aware of. Verify the output for each matched line before running the operation on real data.

Real-world examples

Common situations where this approach makes a real difference:

Reformatting date strings from YYYY-MM-DD to DD/MM/YYYY

A data migration task needs to reformat thousands of ISO date strings scattered through a CSV to European DD/MM/YYYY format for a new reporting system. Find pattern: (\d{4})-(\d{2})-(\d{2}). Replacement string: $3/$2/$1. Testing against "Created on 2024-03-15 and updated 2024-11-01" in the tester produces "Created on 15/03/2024 and updated 01/11/2024". Both dates are reformatted correctly in a single pass. The developer confirms the output before running the equivalent sed command across the production CSV file containing over 200,000 rows.

Renaming function parameters in a large TypeScript codebase

A codebase refactor requires changing userId to accountId across function signatures, call sites, and destructuring patterns, but must not affect "userId" inside string literals, comments, or template strings. Find pattern: (\(|,\s*)userId(\s*[:,)]). Replacement: $1accountId$2. Pasting 20 representative lines including function declarations, call expressions, and destructuring assignments into the tester confirms the replacement correctly renames the parameter in all structural positions while leaving string literal and comment occurrences untouched.

Transforming markdown link syntax to HTML anchor tags

A static site generator script converts markdown [text](url) links to HTML anchor tags for a legacy template system. Find pattern: \[([^\]]+)\]\(([^)]+)\). Replacement: <a href="$2">$1</a>. Testing against "[FixTools](https://fixtools.io) is a free developer toolkit" produces <a href="https://fixtools.io">FixTools</a> is a free developer toolkit, confirming that group $1 contains the link text and group $2 contains the URL. The developer also tests a markdown link with punctuation in the title to confirm the negated character class handles it.

Stripping HTML tags from text content

A content API response contains inline HTML tags that must be removed before the text is stored in a plain-text search index. Find pattern: <[^>]+>. Replacement: empty string. Testing against "<p>Hello <strong>world</strong></p>" in the tester produces "Hello world", confirming all opening and closing tags are removed. The developer tests a self-closing <br /> tag and a tag with multiple attributes including class and data attributes to confirm the negated character class [^>]+ handles all tag forms correctly before applying the replacement to the full API response corpus.

When to use this guide

Use this page before running a regex find-and-replace in your IDE, a sed command, or a String.replace() call in code, especially when the replacement uses capture groups or back-references.

Pro tips

Get better results with these expert suggestions:

1

Use named groups in replacement strings for self-documenting transforms

Replace numbered capture groups like (\d{4})-(\d{2})-(\d{2}) with named groups (?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2}) so the replacement string reads $<day>/$<month>/$<year> instead of $3/$2/$1. Named references do not break when you add a new group to the pattern, because the reference is by name rather than position. Numbered $1, $2 references silently shift when group count changes, which is a frequent source of replacement bugs during pattern maintenance.

2

Test your replacement string against optional capture groups explicitly

If a capture group is inside an optional part of the pattern, such as (\+\d{1,3})?, it will be undefined for inputs where the optional section does not appear. In JavaScript, referencing an undefined group in a replacement string produces the literal text "undefined" in the output rather than an empty string. Test your replacement against both inputs where the optional group matches and inputs where it does not, to confirm the output is correct in both cases before running on real data.

3

Use the Diff Checker after replacement to verify large-scale changes

After running a regex replace operation across a large file or database, paste the original content and the result into the FixTools Diff Checker. The side-by-side diff view reveals every line that changed, making it easy to spot unintended replacements where the pattern matched text you did not intend to transform. This verification step is especially valuable for code refactoring replacements where many lines share similar structure and a too-broad pattern can make changes you do not notice at a glance.

4

Escape dollar signs and backslashes in literal replacement text

If your replacement string needs to contain a literal dollar sign, escape it as $$ in a JavaScript String.replace() replacement string: $$100 produces the literal output $100. Without escaping, the engine tries to interpret $1 as a back-reference to the first capture group. In Python re.sub() replacement strings, literal dollar signs do not need escaping. In sed, use \$ for a literal dollar sign. Test replacement strings containing these characters in the tester to verify the output contains the intended literal text.

FAQ

Frequently asked questions

Wrap the text you want to reuse in parentheses to create a capture group. In the replacement string, reference it as $1 for the first group and $2 for the second in JavaScript String.replace(). For named groups (?<name>...), use $<name> in the replacement. For Python re.sub(), use \1, \2, or \g<name>. Test both the find pattern and the replacement string in the tester together to confirm the captured text appears in the correct position in the output before applying to real data.
In JavaScript, omit the g (global) flag from your pattern. Without g, String.prototype.replace() replaces only the first match found and leaves the rest unchanged. In Python, re.sub() replaces all occurrences by default; pass count=1 to limit replacement to the first match: re.sub(pattern, replacement, string, count=1). In sed, a replacement without the trailing g modifier replaces only the first match on each line by default.
Yes. Use an empty string as the replacement to delete every match. In JavaScript: string.replace(/pattern/g, ''). In Python: re.sub(r'pattern', '', string). In sed: s/pattern// with g for global deletion. Test the deletion pattern in the tester first to confirm your pattern matches only the text you intend to remove. An overly broad pattern can silently remove content you want to keep if it is not verified before execution.
This usually means the capture group did not participate in the match. If the group is inside an optional or alternating section that was not entered for a particular match, the group is undefined, and some engines produce the literal reference string rather than an empty string. Verify in the tester that the group is shown in the match results panel for the specific input you are testing. Also confirm you are using $1 in the JavaScript replacement string rather than \1, which is the Python and sed syntax and is not recognised as a back-reference in JavaScript.
Escape it as $$ in a JavaScript String.replace() replacement string. For example, to replace the word "price" with "$100", use the replacement string "$$100". Without the double dollar sign, the engine interprets $1 as a back-reference to the first capture group, not as literal $1. In Python re.sub(), a literal $ in the replacement string does not need escaping. In sed, use \$ to include a literal dollar sign in the replacement.
Use the FixTools online tester to paste a sample of your data and see the replacement output without touching any files. For command-line workflows, sed can preview output by omitting the -i flag: sed 's/pattern/replacement/g' file.txt streams the transformed content to the terminal without modifying the source file. Review the output to confirm it looks correct before re-running the same command with -i to apply the replacement in place.
In JavaScript, you can pass a function as the second argument to String.replace(). The function receives the full match, each capture group value, the match index, and the original string as arguments, and returns the replacement string. This enables transforms like title-casing matched words, number formatting, or conditional replacements based on group content. Test the find pattern in the tester first to confirm the capture structure is correct, then write the replacement function with confidence that it will receive the expected arguments.
Enable both the g (global) and m (multiline) flags. The g flag finds all matches rather than stopping after the first. The m flag makes ^ and $ match line boundaries rather than string boundaries, which is necessary if your pattern uses anchors that must match at the start or end of each line rather than the entire string. Test the pattern with both flags active against a multi-line sample to confirm matches are found on every line before running the replacement on your full dataset.
Regex replace is fine for surface-level edits where the surrounding structure of the document is irrelevant: bulk-renaming a variable in plain text, reformatting dates in a CSV column, or stripping a uniform prefix from log lines. It becomes the wrong tool the moment context matters. If you need to rename a JavaScript variable only when it appears in scope but not when it appears inside a string literal or comment, regex cannot tell the difference reliably. The right tool is a code transformer like jscodeshift, ts-morph, or Babel that operates on the abstract syntax tree. For HTML, use DOMParser to walk the tree and edit nodes; for JSON, parse, mutate, stringify. Reach for regex replace only when the cost of running a parser is unjustified for the simplicity of the change.
Two patterns recur in real incidents. First, naive HTML sanitisation by regex: stripping <script> tags with a replace looks like it removes the threat but misses event-handler attributes, javascript: URLs in href values, and SVG-based payloads. The only reliable HTML sanitiser is a parser-based library like DOMPurify. Second, log injection via replacement: if user input flows into a replacement string with $1 or $<name> references resolving from an attacker-controlled regex, the attacker can splice arbitrary characters into the output, including newlines that forge fake log lines. Always treat user-supplied patterns and user-supplied replacement strings as untrusted, validate them against an allowlist of safe constructs, and escape the resulting output for the downstream context.

Related guides

More use-case guides for the same tool:

Ready to get started?

Open the full Regex Tester — free, no account needed, works on any device.

Open Regex Tester →

Free · No account needed · Works on any device