Skip to content

Regex Tester guide

Tool guide. Updated .

How to test JavaScript regular expressions with the XGM Regex Tester: flags, groups, replacement syntax, and how to avoid slow patterns and mistakes.

Regular expression basics

A regular expression describes a set of strings with a compact syntax: literal characters, character classes, quantifiers and groups. Engines scan the input and report where the pattern matches. The XGM tester uses the browser's JavaScript engine, so results match what String.prototype.match, matchAll and replace do in your code.

Syntax you will use most
SyntaxMeaningExample
.Any character except line breaks (unless s)a.c matches abc
\d, \w, \sDigit, word character, whitespace\d{4} matches 2026
[abc], [^abc]One of, or none of, the characters[aeiou]
*, +, ?0 or more, 1 or more, 0 or 1colou?r
{n,m}Between n and m repetitions\d{2,4}
^, $Start and end of input (or line with m)^Error
\bWord boundary\bcat\b
( ), (?<name> )Capturing group, named group(?<year>\d{4})
(?: )Non-capturing group(?:https?|ftp)://
a|bAlternationjpg|png
(?= ), (?! )Lookahead, negative lookahead\d+(?=px)
How the Regex Tester evaluates a patternThe pattern and flags are compiled in a web worker, run against the test text with a time limit, and the matches, groups and optional replacement are sent back to the page.Pattern and flagsJavaScript syntax without surrounding slashesCompile in a web workerSyntax errors are reported with the engine'smessageRun against the test textStopped after 1.5 seconds if it takes too longMatches and groupsHighlighted text, numbered and named capturesper matchOptional replaceReplacement using $1, $<name> and $&
The pattern and flags are compiled in a web worker, run against the test text with a time limit, and the matches, groups and optional replacement are sent back to the page.

How to use the Regex Tester

  1. Open the Regex Tester and enter the pattern without the surrounding slashes, for example (?<year>\d{4})-(?<month>\d{2}).
  2. Set flags such as g, i or m.
  3. Paste test text. Matches are highlighted and listed with their groups.
  4. Enable Replace and enter a replacement to preview the result, using $1, $<name> or $&.

A practical example: to find host names under example.com in a log, the pattern \b[a-z0-9-]+\.example\.com\b with the gi flags matches www.example.com and API.example.com but not example.com.evil.example.net, because of the word boundary after com. Try variations in the tester to see which lines match and why.

Keep a set of test lines with the pattern, for example in a comment next to the code. When someone changes the pattern later, pasting those lines into the tester shows immediately whether behaviour changed.

Test with realistic text, including the cases that should not match. A pattern that finds every valid date is only half done until you have checked that it also rejects 2026-13-45 or a phone number that looks similar.

Flags

JavaScript regex flags
FlagNameEffect
gGlobalFind all matches instead of the first
iIgnore caseCase-insensitive matching
mMultiline^ and $ match at line starts and ends
sdotAll. also matches line breaks
uUnicodeUnicode code points and \p{…} property escapes
vUnicode setsLike u, plus set operations in classes; not combined with u
yStickyMatch only at the current position (lastIndex)
dIndicesReport start and end indices of groups

The u flag matters for anything beyond ASCII. Without it, an emoji counts as two separate code units, and \p{L} for "any letter" is not available. With u, \p{L}+ matches words in any script, such as Ștefan or Zürich.

Replacement syntax

Special patterns in the replacement text
PatternInserts
$&The whole match
$1, $2, …Numbered group
$<name>Named group
$$A literal dollar sign
$'Text after the match (a dollar sign followed by a backtick inserts the text before it)
Reformatting dates
Pattern:     (?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})
Flags:       g
Replacement: $<day>.$<month>.$<year>

Input:  Released 2026-09-15, patched 2026-10-01
Output: Released 15.09.2026, patched 01.10.2026

Slow patterns and catastrophic backtracking

JavaScript's regex engine uses backtracking: when part of a pattern fails, it goes back and tries other ways to match. Nested quantifiers over overlapping characters, such as (a+)+$ or (\w|\d)*x, can make the number of attempts grow exponentially with input length. A few dozen characters can then take seconds or longer.

This is a real security issue called ReDoS (regular expression denial of service): a server that runs such a pattern on user input can be stalled by one crafted request. The tester runs patterns in a web worker and stops after 1.5 seconds, so you see "Stopped after 1.5 seconds" instead of a frozen tab.

Rewriting risky patterns
RiskySaferWhy
(a+)+a+Nested quantifiers over the same characters
(\w|\d)*\w*\d is already part of \w, so alternatives overlap
.*.*=[^=]*=Two greedy wildcards compete for the same text
^(\s*\w+\s*)+$^\s*\w+(?:\s+\w+)*\s*$Make separators mandatory between repetitions

Limit input on servers

Validate the length of user input before applying regular expressions, and prefer simple, anchored patterns. For complex formats such as email addresses or URLs, use a parser instead of a giant pattern.

Common mistakes

  • Forgetting to escape. . matches any character; use \. for a literal dot, for example in example\.com.
  • Unanchored validation. \d{5} matches inside 123456; use ^\d{5}$ to validate a whole value.
  • Greedy wildcards. <.*> matches from the first < to the last > on the line; use <[^>]*> or the lazy <.*?>.
  • Escaping twice in code. A pattern written as a string in JavaScript needs double backslashes ("\\d"); the tester expects the regex literal form (\d).
  • Using `g` with `test()` in a loop. The global flag keeps lastIndex between calls, so repeated test calls on the same regex alternate between true and false.

For URLs, the URL & UTM breaks an address into its parts more reliably than a pattern. For data formats, the JSON Formatter validates structure properly.

FAQ

Which regex flavour does the tester use?

JavaScript, as implemented by your browser. Results match what the same pattern does in JavaScript code in that browser.

Why does my pattern from Python or PCRE not work?

Flavours differ. JavaScript has no possessive quantifiers, no atomic groups and no inline modifiers like (?i) in most browsers, and some escapes behave differently.

Why was my test stopped after 1.5 seconds?

The pattern backtracked too much on the input, a sign of catastrophic backtracking. Simplify nested or overlapping quantifiers.

How do I match across lines?

Use the s flag so . matches line breaks, or [\s\S]. Use m if you want ^ and $ to match at each line.

What is the difference between $1 and $<name>?

$1 refers to a group by position; $<name> refers to a named group and keeps working when you add groups.

Is my test text uploaded?

No. The pattern and text are processed in your browser, in a worker thread of the page.

Can regex validate email addresses?

Only approximately. The full address syntax is complex; a simple pattern plus a confirmation email is the practical approach.

What does the d flag do?

It adds start and end indices for each capture group to match results, useful for highlighting or editors.

Should I use regex to parse HTML?

Not for anything beyond simple, known snippets. HTML nesting and optional syntax make patterns fragile; use the browser's DOM parser or a proper HTML parsing library.

Why does \w not match accented letters?

\w means ASCII letters, digits and underscore. Use \p{L} with the u flag for letters in any script.

Sources