Regex Tester – Match & Replace

Test JavaScript regular expressions live: every match highlighted, capture groups and named groups listed, search and replace with $1 / $<name>. Slow patterns are stopped after one second instead of freezing your tab.

/ /
Matches:0
Groups:0
Time:–
Highlighted matches

How to Use the Regex Tester

Type your pattern between the slashes and your test text below it — matches are highlighted as you type, there is no button to press. You can also paste a complete regex literal such as /\d+/gi into the pattern field; the tool splits it into pattern and flags for you.

  • Flags — tick the boxes or type the letters into the small field after the closing slash. Both stay in sync.
  • Match list — each match with its position (index and line:column), its length and every capture group. Named groups are labelled with their name. A group that did not take part in the match is shown as not matched, which is different from a group that matched an empty string.
  • Empty matches — patterns like \b, ^ or a* can match zero characters. They are shown as a thin marker in the text instead of disappearing.
  • Replace — switch to the Replace tab, enter a replacement and get the full result text, ready to copy.
  • Examples — load a ready-made pattern with matching sample text to see how it works, then change it.
  • Copy as JavaScript — copies the regex as a literal and as a new RegExp() call with the string correctly escaped.
  • Share link — copies a URL that reopens the tester with your pattern, flags, replacement and (if it is short enough) the test text.

Search and Replace with Capture Groups

In Replace mode the tool uses exactly the same rules as JavaScript’s String.prototype.replace(), so what you see is what your code will do:

  • $1, $2 … — the text of capture group 1, 2 and so on.
  • $<name> — the text of a named group (?<name>…).
  • $& — the whole match. $` and $' insert the text before and after the match.
  • $$ — a literal dollar sign.

Without the g flag only the first match is replaced — a common surprise. Example: the pattern (?<last>\w+),\s*(?<first>\w+) with the replacement $<first> $<last> turns “Lovelace, Ada” into “Ada Lovelace”. To insert a line break, tick Treat \n and \t as line break and tab; in your own code you would write "\n" in the string literal instead.

Protection Against Catastrophic Backtracking

Some patterns take exponential time on certain inputs. The classic example is (a+)+$ tested against a long run of a followed by a b: the engine tries every possible way of splitting the as between the inner and outer loop before it gives up. In most online testers this freezes the browser tab. Here the matching runs in a background worker; if it takes longer than one second it is stopped and you get a clear message instead. If that happens to a pattern you plan to use in production, take it seriously — the same input can stall a server (this is known as ReDoS). Fixes are usually to remove nested quantifiers, make alternatives mutually exclusive, or anchor the pattern.

Regex Flags Reference

  • g (global) — find all matches, not just the first one. Needed for “replace all”.
  • i (ignore case) — /hello/i matches “Hello”, “HELLO” and “hello”.
  • m (multiline) — ^ and $ match at the start and end of every line, not only of the whole text.
  • s (dotAll) — . also matches line breaks.
  • u (unicode) — treats emoji and other characters outside the Basic Multilingual Plane as one character and enables \p{L}-style Unicode property escapes. It also makes the syntax stricter: a stray escape like \- outside a character class becomes an error.
  • y (sticky) — a match must start exactly where the previous one ended. Useful for tokenizers.

Quick Reference — Regex Syntax

  • . — any character (except line breaks without the s flag)
  • \d \w \s — digit, word character [A-Za-z0-9_], whitespace; \D \W \S are the opposites
  • [abc] [^abc] [a-z] — character class, negated class, range
  • * + ? {n,m} — zero or more, one or more, optional, between n and m times; add ? to make them lazy (.*?)
  • (…) (?:…) (?<name>…) — capture group, non-capturing group, named group
  • \1 \k<name> — back-reference to an earlier group
  • a|b — alternation (a or b)
  • ^ $ \b — start, end, word boundary
  • (?=…) (?!…) (?<=…) (?<!…) — lookahead, negative lookahead, lookbehind, negative lookbehind
  • \p{L} \p{Lu} \p{Emoji} — Unicode properties (need the u flag)

Common Regex Patterns

All of these are in the Load an example menu above, with sample text to try them on.

  • Email (pragmatic): [\w.+-]+@[\w-]+(\.[\w-]+)*\.[A-Za-z]{2,} — good for finding addresses in text; to really validate one, send a confirmation mail.
  • URL: https?:\/\/[^\s/$.?#][^\s]*
  • IPv4 address (0–255 per part): \b(?:(?:25[0-5]|2[0-4]\d|1?\d?\d)\.){3}(?:25[0-5]|2[0-4]\d|1?\d?\d)\b
  • ISO date: (?<year>\d{4})-(?<month>0[1-9]|1[0-2])-(?<day>0[1-9]|[12]\d|3[01])
  • Hex colour: #(?:[0-9a-fA-F]{3}){1,2}\b
  • Repeated word: \b(\w+)\s+\1\b with the i flag

Frequently Asked Questions

Which regex flavor does this use?

JavaScript (ECMAScript) — the engine built into your browser, the same one Node.js, Deno and Bun use. It supports lookahead and lookbehind, named groups, back-references and Unicode property escapes. It does not support PCRE-only features such as possessive quantifiers, atomic groups, recursion or inline modifiers like (?i). Most simple patterns behave the same in Python, Java, PHP and Go, but test the details in the target language.

Is my data safe?

Yes. All matching runs in your browser. Neither the pattern nor the text is sent to a server. The share link only contains what you choose to share, and only when you click the button.

Why does my regex time out?

The pattern most likely causes catastrophic backtracking: nested quantifiers like (a+)+ or (\w*)*, or alternatives that can match the same text like (a|a)*. The tester stops after one second to keep the page responsive. Rewrite the pattern so that each character can be matched in only one way.

What is the difference between “not matched” and an empty group?

In (a)|(b) matching “b”, group 1 did not participate at all — in JavaScript it is undefined, shown here as not matched. In (a*)b matching “b”, group 1 participated but matched zero characters — it is an empty string "". The difference matters when your code checks if (match[1]).

How do I match a literal special character?

Escape it with a backslash: \. matches a period, \* an asterisk, \/ a slash. The characters that need escaping are . * + ? ^ $ { } [ ] ( ) | \ and, in a JavaScript regex literal, /.

What is a capture group?

Parentheses () capture the part of the match inside them. (\d{4})-(\d{2})-(\d{2}) applied to “2026-04-02” captures “2026”, “04” and “02”. Give them names with (?<year>\d{4}) to read them as match.groups.year in code and use $<year> in replacements.