Regex Tester

Test and debug regular expressions with real-time match highlighting. Supports global, case-insensitive, and multiline flags.

//g
Flagsglobal
0 characters
With

Patterns here are compiled by your browser's actual JavaScript RegExp engine — the same one running in Chrome and Node — so what matches in this tester is exactly what will match in your code. Matches re-evaluate live as you type, with inline highlighting, a per-match index and capture-group listing, and a replace preview.

Type the pattern bare — no slashes, no double escaping

The field expects just the pattern: [a-z]+ rather than /[a-z]+/g. If you paste a pattern with its slashes, they are treated as literal characters to match. Flags live in the three toggle buttons instead. The flip side is convenient: because this is not a JavaScript string literal, \d and \b work typed directly — none of the \\d doubling you need inside new RegExp("...").

Which flags exist here, and what the missing ones cost you

You get g (find all matches), i (case-insensitive), and m (^ and $ match at line breaks). There is no s toggle, so the dot never matches a newline in this tester — /a.b/ fails against a<newline>b; use [\s\S] to cross lines. There is no u or v toggle either, which fails silently rather than loudly: \p{L} does not error, it just matches nothing, because without the u flag the engine reads it as a literal p{L} sequence. Lookbehind, on the other hand, works — (?<=\$)\d+ is fine in any current browser, though it will still throw in older Safari.

What the g flag actually changes

With g off, you get the first match only, and the replace preview substitutes only the first occurrence — replacing a in aaa yields Xaa, not XXX. That trips people up more in replace than in match. One more edge this tool handles explicitly: a pattern that can match empty strings, like x*, produces zero-length matches at each position (three of them against the two-character string ab), shown as "empty match" rather than looping forever.

Lookbehind extraction (flags: g)
Input: pattern (?<=\$)\d+(\.\d+)? on "price: $42.99, cost: $7"
Output: 2 matches: 42.99, 7
The $ anchors the match position but stays out of the captured text.
Group references in replace
Input: pattern (\w+) (\w+), replacement $2, $1, on "John Smith"
Output: Smith, John
$1 and $2 refer to capture groups; a literal dollar sign in the replacement is written $$.

Questions people ask

Do named groups like (?<year>\d{4}) work?

They match correctly, and $<year> works in the replacement field. The match-details panel, however, lists all groups by position number, so a named group shows up as group 1, group 2, and so on rather than by its name.

Why do I get more matches than there are occurrences?

Your pattern can match the empty string — quantifiers like * and ? make everything optional. The engine then finds a zero-length match at every position between characters, which is why x* reports three matches against ab. Anchor the pattern or use + so at least one character is required.

For comparing two whole blocks of text rather than pattern-matching one, the text diff tool is the better fit; the cron parser covers the other mini-language people commonly debug by trial and error.

Further reading