Test regular expressions and understand them
This tester highlights every match live as you type and gives a plain-English, step-by-step explanation of what each part of your pattern does — something most regex tools skip. It is built for developers writing and debugging patterns, and for anyone learning regex who wants to know why a pattern matches.
Compiled by the real engine, explained token by token
Your pattern and flags are compiled with the browser’s native
new RegExp(pattern, flags) — the exact JavaScript engine your code will use, so
behaviour matches production. For highlighting, the tester forces the global flag
(g) internally and runs test.replace(regex, ...) to wrap every match in a
highlight, even if you didn’t type g. If the pattern is invalid, the RegExp
constructor’s error is shown instead. Separately, a lightweight tokeniser walks
the pattern left to right and emits a sentence per token (character class,
quantifier, anchor, group, alternation, and so on) for the explanation panel.
Example
Pattern \b\d{4}-\d{2}-\d{2}\b with the g flag, tested against:
Invoices dated 2026-05-30 and 2026-06-01 are due.
highlights both 2026-05-30 and 2026-06-01. The explainer breaks it down as:
word boundary, four digits, a literal hyphen, two digits, a hyphen, two digits,
word boundary — i.e. an ISO-style date.
Flag reference
| Flag | Name | Effect |
|---|---|---|
g | global | Match every occurrence, not just the first |
i | ignore case | Case-insensitive matching |
m | multiline | ^ and $ match at each line break |
s | dotall | . also matches newline characters |
Pattern building guide
Understanding a few core building blocks lets you read almost any pattern without reaching for a reference every time.
Anchors — locking position
^matches the start of the string (or line, with themflag)$matches the end of the string (or line)\bmatches a word boundary — the transition between a word character and a non-word character
Character classes
\d— digit (0–9);\D— non-digit\w— word character (letters, digits, underscore);\W— opposite\s— whitespace;\S— non-whitespace[abc]— any of a, b, or c;[^abc]— none of those[a-z]— lowercase range;[A-Za-z0-9]— alphanumeric
Quantifiers
?— zero or one time;*— zero or more;+— one or more{n}— exactly n;{n,m}— between n and m- Append
?to any quantifier to make it lazy:.*?matches as little as possible
Groups and alternation
(abc)— capturing group;(?:abc)— non-capturing group(?<name>...)— named capture group; reference with\k<name>or$<name>in a replacementa|b— alternation: matches a or b
Lookarounds — matching without consuming
(?=...)— positive lookahead: the position must be followed by the pattern(?!...)— negative lookahead: must not be followed by it(?<=...)— positive lookbehind: must be preceded by the pattern(?<!...)— negative lookbehind: must not be
Lookarounds assert a condition without including it in the match. A classic use:
\d+(?= USD) matches the number in 100 USD but not the currency code itself.
JavaScript has supported lookbehind since ES2018, so all current browsers run it
natively. The full syntax is defined in the
ECMAScript language specification,
and MDN’s regular-expressions guide
is the best practical reference for the JavaScript flavour this tool uses.
Recipes you can paste straight in
| Goal | Pattern | Note |
|---|---|---|
| ISO date | \b\d{4}-\d{2}-\d{2}\b | Format check only — accepts 2026-99-99 |
| Time (24h) | \b([01]\d|2[0-3]):[0-5]\d\b | Hours 00–23, minutes 00–59 |
| UK postcode (loose) | \b[A-Z]{1,2}\d[A-Z\d]? ?\d[A-Z]{2}\b | With i flag for lowercase |
| Trailing whitespace | [ \t]+$ | Use with m flag to clean line ends |
| Duplicate word | \b(\w+)\s+\1\b | Backreference \1 repeats group 1 |
| Number with decimals | -?\d+(\.\d+)? | Optional sign and fraction |
Treat format patterns as shape checks, not validity checks — a regex can confirm a string looks like a date or an email, but not that the date exists or the mailbox receives mail.
A caution on catastrophic backtracking
Some patterns are dangerous in production even though they look innocent. Nested
quantifiers over overlapping alternatives — the classic being (a+)+$ — can force
the engine into exponential backtracking on a non-matching input, freezing the
event loop. This failure mode is known as
ReDoS (regular expression denial of service),
and it matters whenever a user-supplied string meets a complex pattern on a
server. If a pattern in this tester feels slow on a long input, that is the same
backtracking at small scale: rewrite nested quantifiers, anchor the pattern, or
replace ambiguous groups with atomic alternatives.
Debugging tips
- If the pattern matches more than expected, a greedy quantifier is likely consuming too much — add
?to make it lazy. - If nothing matches, check that you have not accidentally escaped a character you didn’t mean to, or that you need the
mflag for multi-line input. - If you get a
SyntaxError, the invalid-pattern box shows the engine’s message — look for unmatched parentheses or an incomplete escape sequence.
Everything runs locally in your browser — your pattern and text are never uploaded.