Regex Tester
What it does
The Regex Tester takes a regular expression pattern, applies it to test text, and shows you what matches and where. Matches are highlighted inline within the text. Capture groups (parenthesised parts of the pattern) appear in a numbered breakdown for the first match. An optional replace mode lets you transform the matched text using replacement strings with $1, $2 substitution. Six flags (global, case-insensitive, multiline, dot-all, unicode, sticky) toggle on and off independently. It sits inside our developer tool suite alongside the other utilities you reach for while writing and debugging code.
Common situations
You’re tuning a regex iteratively. The first attempt matches too much; the second attempt matches too little. Each adjustment needs verification against your test data. Reaching for the language REPL (Python, JavaScript console, Ruby’s irb) means typing the pattern and printing the matches each time. Doing it here with live match highlighting is faster. Change a character, see the matches update.
You’re debugging a regex that worked yesterday and stopped working today. Some new edge case in the input is misbehaving. Pasting the pattern, the input that broke it, and the input that still works lets you see at a glance which part of the pattern is misfiring. The diagnosis usually takes seconds once you can see what is matching where.
You’re verifying a regex copied from Stack Overflow before committing it to your codebase. The internet is full of regex one-liners that mostly work for some definition of “mostly”. Testing against your specific data before deploying is faster than debugging it in production three weeks later.
You’re producing a regex for a content editor’s “find and replace” task: replacing all instances of <old-tag> with <new-tag> in a CMS, normalising phone number formats across a database export, stripping tracking parameters from URL lists. Building the pattern with live highlighting and replace preview catches the corner cases (the rogue <old-tag-extended> your simple pattern would also match) before the bulk operation.
You’re learning regex syntax. Live feedback on what each pattern element does is the fastest way to internalise the language. Toggling flags individually shows their effects in isolation; capture groups make grouping behaviour visible.
What you need to know
The browser’s RegExp constructor compiles the pattern with the flags you select; matching uses regex.exec in a loop for global matches or single String.match otherwise. Capture groups are pulled directly from the result array. result[0] is the whole match, result[1] is the first parenthesised group, and so on.
Replace mode runs String.replace(regex, replacement) and shows the output. The $1, $2 syntax in the replacement is JavaScript’s standard back-reference form: match the first capture group, replace with what was captured. Special replacement tokens include $& for the whole match, $` for everything before the match, and $' for everything after.
Match highlighting walks the text from left to right, copying non-matching segments verbatim and wrapping matching segments in styled spans. Special characters in the input are HTML-escaped so a regex matching <script> does not actually inject script tags into the rendered preview.
Flags modify regex behaviour:
- g (global): find all matches, not just the first. Without it,
matchreturns the first; with it, all matches. - i (case-insensitive):
ABCmatchesabc,Abc,ABC, etc. - m (multiline):
^and$match line boundaries, not just string start/end. - s (dotAll / single-line):
.matches newlines, which it normally does not. - u (unicode): proper handling of multi-byte characters (emoji, CJK, mathematical symbols).
- y (sticky): match must start at the regex’s
lastIndexposition.
Performance pitfalls: nested quantifiers ((a+)+) can produce exponential matching time on certain inputs (catastrophic backtracking). If your tester hangs, the pattern is the suspect. Simplify or rewrite to avoid nested ambiguity.
JavaScript’s regex engine has differences from other dialects. Lookbehinds ((?<=...)) work in modern browsers but not older runtimes. Named capture groups ((?<name>...)) work everywhere modern. b word boundaries treat underscores as word characters, which surprises people coming from PCRE. Many “this regex doesn’t work in JavaScript” issues trace to dialect differences.
Frequently asked questions
How do I test a regular expression?
Type the pattern into the field, paste your test text below, watch the matches highlight. Adjust the pattern until the matches reflect what you want. The flags toggle changes whether the regex is global, case-insensitive, multiline, etc.
What does the “g” flag do?
Global. Without it, only the first match is found. With it, all matches in the text are found. Most “why is my regex only matching once?” questions have this as the answer.
What’s the difference between greedy and lazy quantifiers?
* and + are greedy, so they match as much as possible. *? and +? are lazy, so they match as little as possible. <.*> matches across multiple HTML tags; <.*?> matches one tag at a time.
How do I use capture groups?
Wrap part of the pattern in parentheses: (w+)@(w+) captures the username and domain of an email-like pattern. Reference the captures as $1, $2 in replace mode, or as result[1], result[2] in code.
Why doesn’t my regex work for emoji?
Without the u (unicode) flag, multi-byte characters like emoji can produce unexpected matches. Add the unicode flag and the regex handles them correctly.
What’s a lookbehind?
A zero-width assertion that matches a position based on what comes before it. (?<=$)d+ matches digits that are preceded by a dollar sign, without including the dollar sign in the match. Lookaheads ((?=...) and (?!...)) work similarly looking forward.
Why does my regex with ^ and $ only match the very start and end of the input?
Without the m (multiline) flag, ^ and $ match the start and end of the entire string. With m, they match the start and end of each line. Toggle the flag based on whether you want line-level or string-level anchoring.
Are JavaScript regex and Python regex the same?
Mostly. Both follow the same broad regex tradition. Differences exist around lookbehinds, named groups, character classes, and Unicode handling. A pattern that works in one may fail in the other; test in the actual target language before deploying.
Common problems
Problem: The regex matches once and stops, even though I want all matches.
Add the g (global) flag. Without it, match returns only the first match. The flag toggles next to the pattern field.
Problem: A regex with
.+is hanging, possibly forever.
Catastrophic backtracking. Patterns with nested quantifiers ((a+)+, (.*)+) can produce exponential matching time on certain inputs. Rewrite to avoid nested ambiguity, usually possible by making the inner quantifier lazy or using atomic groups.
Problem: My regex matches what I expect in the tester but not in production code.
Different regex engines have subtly different syntax. PCRE (PHP, many Linux tools), JavaScript (browsers), Python’s re module, and POSIX BRE/ERE all have edge-case differences. Test the pattern in the actual target language, not just here.
Problem: Replace mode produces literal
$1in the output instead of the capture.
The capture group is undefined or did not match. $1 substitutes the first capture group’s matched text; if the group did not capture anything (e.g. inside a non-matching alternative), the substitution becomes the literal $1. Verify the match has captures.
Problem: Highlighting works for ASCII text but breaks on emoji or accented characters.
Without the u flag, multi-byte characters can produce surprising matches because the regex engine works on UTF-16 code units rather than Unicode code points. Add u and the regex handles them correctly.
Quick guides
For JavaScript: Patterns and flags are the same as the tester. Use new RegExp(pattern, flags) to construct, or /pattern/flags literal syntax. string.matchAll(regex) for iterating all matches with capture groups.
For Python: Patterns mostly transfer; flag names differ (re.IGNORECASE for i, re.MULTILINE for m, etc.). Lookbehinds need fixed-width strings in older Python versions; this is fine in 3.7+.
For Bash / grep: Use grep -E for extended regex (closer to JavaScript syntax) or grep -P for PCRE (closer to JavaScript with extensions). Plain grep uses BRE, which has different escaping rules.
Tips
- The
g(global) flag changes behaviour significantly. Without it, only the first match is found; with it, all matches. Most “why is my regex only matching once?” questions have this as the answer. - Capture groups are not the same as match positions. A regex with
(w+)@(w+)matchingalice@exampleproduces three values: the full matchalice@example, group 1alice, group 2example. Using the wrong index is a common bug. - Anchoring with
^and$interacts with the multiline flag. Withoutm, they match the start and end of the whole input. Withm, they match the start and end of each line. - The unicode (
u) flag enables proper handling of code points above the BMP: emoji, certain CJK characters, mathematical symbols. If you see strange behaviour matching emoji, the missing flag is usually the cause. - Lookbehinds (
(?<=...)and(?<!...)) are supported in modern browsers but not in all older runtimes. Worth knowing if your code might run somewhere unusual. - For “find or” patterns, alternation (
a|b|c) matches any one of the alternatives. The leftmost match wins, so order alternatives from most-specific to least-specific. - Regex performance scales with input size and pattern complexity. For very large inputs (megabytes of text), consider whether a regex is the right tool. Sometimes string operations beat regex on raw speed.
Related tools in this suite
The natural pairing is the Text Diff. When refactoring a pattern, run the old and new outputs through the diff to confirm what actually changed in matched text. The JSON Formatter is a frequent prerequisite when the input you want to regex-against is JSON that needs structural exploration first.
Take it further
A regex that has earned its place in a codebase deserves a unit test, not just verification with a tool. The services we deliver often include test infrastructure that turns “I checked it manually with a regex tester” into “the matcher has a permanent test suite covering the edge cases we have seen and the ones we haven’t yet”. The free tool is the right shape for figuring out the pattern; the codebase is the right place to keep it honest.