What this tester does
A regular expression is a small program that describes a shape of
text, and the fastest way to understand one is to watch it work.
Type a pattern, tick the flags it runs under, and give it some real
text: every match is highlighted in place, listed with its exact
position, and unfolded into its capture groups. There is no Run
button because there is nothing to wait for — the results update as
you type, compiled and executed by the same JavaScript
RegExp engine you would ship against, so what matches
here is what matches in your code, including the awkward cases. The
companion regex cheat sheet
covers the syntax itself; this page is the workbench next to it.
How to use it
- Start from a preset if your shape is a common one — email, URL, ISO date, phone number, IPv4 address, hex colour. Each preset fills in a pattern and a sample text with deliberate near-misses, so you can see both what matches and what correctly does not.
- Edit the pattern and watch the highlights move. The match list below numbers every match and shows its start and end positions; expand a match to see what each capture group caught.
- Toggle flags one at a time. Most regex confusion is flag confusion:
mchanges what^and$mean,schanges what.means, andiis usually the difference between a pattern that works on your sample and one that works on production data. - Break it on purpose. Remove an anchor, loosen a quantifier, and look at the extra matches — a pattern is defined as much by what it wrongly accepts as by what it catches.
Reading the results
The highlight view answers "where does it bite?" and the list
answers "what exactly did it take?". A match entry shows the matched
text and its character offsets in the test string — offsets count
from 0, the convention your code uses, so a match at index 4 is the
fifth character. Groups are listed under their match in order:
numbered groups first, then any named groups. A group shown as
undefined sat inside a branch that did not run — an
alternation like (cat)|(dog) always leaves one of its
two groups undefined, which is normal and is exactly the kind of
thing that surprises people in production. Zero-width matches —
where the pattern matched the empty string — appear as thin
markers; they are real matches, and the scan steps past them so a
pattern built on * cannot loop forever. If a pattern
can match in more than a thousand places the list stops at 1,000
and says so: by then the question is never the 1,001st match, it is
why the pattern is that permissive.
Three habits worth stealing
Anchor before you optimise. Most runaway patterns
are simply unanchored: \d+ finds digits anywhere,
including inside words and prices, while \b\d+\b or
^\d+$ says which digits you meant. Test the
negative cases. Every preset sample here includes strings
that must not match — a date with month 13, an IP-shaped
300.1.1.1 — because a pattern you have only fed valid input has not
been tested at all. Beware nested quantifiers. A
shape like (a+)+$ against a long almost-matching
string can take exponential time ("catastrophic backtracking"); if
this page ever feels slow while you type, you have found one, and
the fix is almost always to make the inner and outer quantifiers
want different characters. Your browser runs the pattern, so a
runaway pattern can only stall this tab — in a server it would
stall a request queue.