How it works
Matching runs on your browser's own JavaScript RegExp engine, so results are exactly what new RegExp(pattern, flags) produces. With the g flag on, exec is called in a loop and every match is collected with its string index and capture groups; zero-length matches nudge lastIndex forward by one to avoid an infinite loop. The plain-English breakdown is separate: it walks the pattern character by character and labels each token it recognises.
The six flag checkboxes are the quickest way to change behaviour. Only g is ticked by default, and it decides whether you get the first match or all of them; i, m, s, u and y are off. The pattern box starts with a simple email-shaped expression tested against a sentence containing three addresses. Five preset buttons, Email, URL, IPv4, US phone and ISO date, replace both the pattern and the test string together.
Because this is the JavaScript flavour, PCRE-only syntax such as possessive quantifiers, recursion, or the \A and \z anchors will not behave the way it does in PHP, Python or Perl. The explainer is a flat left-to-right scan rather than a parse tree, so it never shows nesting, and it has no entry for lookbehind or named groups, breaking (?<=x) into a capturing group plus literals. Matching stops after 5,000 results and the table lists 200.
Frequently asked questions
Why am I only getting one match? +
The g flag controls that. With g unticked the tool calls exec once and reports the first match only; tick it and the pattern is run repeatedly across the entire test string until no further matches remain. It is ticked by default.
Does this tester support Python or PCRE regex syntax? +
It runs the JavaScript engine only. Everyday syntax behaves identically, but PCRE-specific constructs will either raise an error or match differently. Anything valid in a browser's RegExp constructor works, including the u and y flags exposed as checkboxes.
How do I see what my capture groups matched? +
The match list table has a Groups column showing $1, $2 and so on for every match, with an empty-set symbol where a group took part in no match. Non-capturing groups written as (?:...) deliberately produce no entry there.
What does the plain-English breakdown actually cover? +
Escapes such as \d, \w, \s and \b, the start and end anchors, the dot, alternation, capturing and non-capturing groups, positive and negative lookaheads, character classes, the three basic quantifiers and {n,m} ranges. Anything else is reported as a literal character.
Is my test data sent to a server? +
No. The pattern and the test string are evaluated in your own browser by its built-in regex engine, with no upload and no server round trip. There is also no save or share link, so refreshing the page resets both fields to the defaults.
Flavours differ more than the syntax suggests
Regular expression syntax looks portable and is not. Lookbehind, named groups, Unicode property escapes and recursion vary between JavaScript, PCRE, Python, Go's RE2 and POSIX implementations, and an expression developed in one can fail or behave differently in another.
RE2 in particular deliberately omits backreferences and lookaround to guarantee linear-time matching, so patterns that rely on them cannot be ported to it at all.
Catastrophic backtracking, and knowing when to stop
Nested quantifiers over overlapping alternatives — the classic `(a+)+b` shape — can make a backtracking engine explore exponentially many paths on a non-matching input. On a server processing untrusted input that is a denial-of-service vector rather than a performance annoyance, and it is one of the more common ways a regex becomes a security bug.
The broader judgement is knowing when a regex is the wrong tool. Anything with genuine nesting — HTML, JSON, arbitrary source code — is not a regular language and cannot be reliably matched by a regular expression, however long the pattern grows. Use a parser.
For patterns that must be maintained, verbose mode with comments and a set of test cases is worth more than cleverness.