Regex Tester
Test regular expressions with highlighted matches, capture groups and a safety timeout.
Regex Tester tool
What this tool does
Type a pattern, pick your flags and paste the text you are trying to match. Every match is
highlighted in place as you type, listed with its offset and length, and broken down into
numbered and named capture groups. A replacement field shows what String.replace
would produce before you commit the change to code.
The pattern runs inside a Web Worker with a hard 1.5-second deadline. If it exceeds that, the worker is terminated and a fresh one takes its place, so an accidentally exponential expression costs you a message on screen instead of a frozen tab.
Common uses
- Checking a validation pattern against the inputs that broke in production, rather than against the three cases you thought of when you wrote it.
- Building a log-parsing expression: name the groups, then read the values out of the match table instead of counting brackets.
-
Rehearsing a find-and-replace before running it across a repository, where
$1pointing at the wrong group is a very quiet mistake. - Working out why a pattern matches once when you expected forty — usually a missing
gflag.
A short example
The pattern (?<user>[\w.]+)@(?<host>[\w.]+) against:
Contact [email protected] or [email protected]
finds two matches. The first starts at offset 8, is 17 characters long, and has
user = "ada" and host = "findtool.dev". With the replacement
$<host> the preview becomes:
Contact findtool.dev or example.org Catastrophic backtracking, and why this page cannot hang
JavaScript's engine backtracks. When a pattern can match the same text in more than one way,
a failure makes it retry every other way before giving up. Nest a quantifier inside a group
that already has one — (a+)+$ — and the number of ways to split a run of
a characters between the two doubles with each character added. Twenty-five
as followed by a b is tens of millions of attempts; thirty-five is
hours.
There is no way to interrupt a running regex from the same thread: no timeout parameter, no
abort signal, no yield point. So this tool does not try — the worker is destroyed
mid-calculation. On a server the same shape of pattern is a denial-of-service vector, which
is why (a+)+ in a request validator is a security finding, not a style nit.
Worth knowing
This is the JavaScript engine, so what works here works in Node and in the browser — not
necessarily in PCRE, Python, Go or grep. Lookbehind is supported here and absent
from Go's RE2 entirely. Named groups are (?<name>…) in JavaScript and Python
but (?P<name>…) in older Python and PHP. Atomic groups and possessive
quantifiers — the usual cure for backtracking elsewhere — do not exist in JavaScript at all.
Offsets are counted in UTF-16 code units, so an emoji advances the index by two unless the
u flag is set.
Frequently asked questions
What is catastrophic backtracking?
Certain patterns — typically nested quantifiers like (a+)+$ — can take exponential time on inputs that nearly match. On a server this is a denial-of-service vector known as ReDoS. This tester runs your pattern in a worker and aborts it after 1.5 seconds so the tab stays responsive.
Do these patterns work in other languages?
This tester uses the JavaScript engine. Core syntax is portable, but lookbehind, named groups and Unicode property escapes differ between JavaScript, PCRE, Python and Go. Always re-test in your target language.