Regex Explainer
Read someone else's JavaScript regular expression token by token — every group, quantifier and flag spelled out, entirely on this device.
Paste a pattern — or a whole /pattern/flags literal — and its breakdown appears here.
Select a line to highlight the exact characters it describes.
This pattern has no capture groups.
- g — globalnot set
- i — ignore casenot set
- m — multilinenot set
- s — dot matches line breaksnot set
- u — unicodenot set
- y — stickynot set
- v — unicode setsnot set
No flags are set.
Run the pattern to see what it matches in the sample text.
This reads the JavaScript dialect only. PCRE, Python, Go and .NET differ — atomic groups, possessive quantifiers and inline comment groups do not exist in JavaScript and are reported as errors here.
Support is read from the browser you are using; Chrome and Edge share an engine with the results checked here, Safari and Firefox differ at the edges.
This explains what the pattern says. It does not say whether it is correct for your data, and it makes no safety claim.
How fast a pattern runs on hostile input is a separate question, and the Regex Tester answers it with a one-second watchdog. Open the Regex Tester
Press ? for shortcuts
Do it offline:$
How to use it
- Paste the pattern. A whole /pattern/flags literal is split for you, and the flags it lifted show as a badge you can undo — nothing is rewritten silently.
- Set the flags you actually ship with. They change the reading, not just the matching: u turns \p{L} into a Unicode property, m re-points ^ and $, s lets the dot cross a line break.
- Read the explanation from top to bottom: one line per part, indented to show what sits inside what. The panels beside it list every capture and every flag's effect.
- Optional: paste sample text to see the pattern run against it. That run happens in a worker with a one-second kill timer, so a slow pattern cannot wedge the tab.
Somebody hands you a pattern and the review is blocked until you know what it says. Paste it here and read it back one part at a time: every group numbered, every quantifier counted, every flag spelled out, beside the exact characters they describe. Nothing is sent anywhere — the reading happens in this tab.
Examples
/^\[(\d{2}:\d{2})\]\s(ERROR|WARN)\s(\w{2,5}):/^ — Matches the start of the text — nothing may come before this point.
\[ — \[ matches [ itself — the backslash only escapes it.
(\d{2}:\d{2}) — Capturing group 1 — what it matches is kept and can be referred to later.
\d{2} — Repeats the item before it exactly 2 times.
\d — \d matches one digit, 0 to 9.
: — Matches : — exactly that one character, code point 58.
\d{2} — Repeats the item before it exactly 2 times.
\d — \d matches one digit, 0 to 9.
\] — \] matches ] itself — the backslash only escapes it.
\s — \s matches one whitespace character — space, tab or line break.
(ERROR|WARN) — Capturing group 2 — what it matches is kept and can be referred to later.
ERROR|WARN — Tries 2 alternatives in order and takes the first one that matches.
ERROR — Alternative 1: the parts listed under it
ERROR — Matches the text ERROR exactly, in that order — 5 characters.
WARN — Alternative 2: the parts listed under it
WARN — Matches the text WARN exactly, in that order — 4 characters.
\s — \s matches one whitespace character — space, tab or line break.
(\w{2,5}) — Capturing group 3 — what it matches is kept and can be referred to later.
\w{2,5} — Repeats the item before it between 2 and 5 times.
\w — \w matches one word character — letter, digit or underscore.
: — Matches : — exactly that one character, code point 58.Three numbered captures, and the indentation is the pattern's own nesting: the two \d{2} lines sit inside group 1 because that is where those characters are. Groups are counted the way the JavaScript engine counts them.
/^(?=.{3,})(?<name>\p{L}+)-(?<id>\d+)$/u^ — Matches the start of the text — nothing may come before this point.
(?=.{3,}) — Looks ahead: what follows must match this, and none of it is consumed.
.{3,} — Repeats the item before it at least 3 times, with no upper limit.
. — Matches any single character except a line break.
(?<name>\p{L}+) — Named capturing group name, which is also group 1 — what it matches is kept under that name.
\p{L}+ — Repeats the item before it one or more times.
\p{L} — \p{L} matches one character that has the Unicode property L.
- — Matches - — exactly that one character, code point 45.
(?<id>\d+) — Named capturing group id, which is also group 2 — what it matches is kept under that name.
\d+ — Repeats the item before it one or more times.
\d — \d matches one digit, 0 to 9.
$ — Matches the end of the text — nothing may come after this point.The lookahead consumes nothing: it only asserts that three characters are available before the named part starts. Drop the u flag and the reading changes — \p{L} stops being a Unicode property, and a note says so rather than letting it quietly match four literal characters.
/(?>a)b/Position 1: '(?>' is an atomic group, which exists in PCRE, Perl and .NET but not in JavaScript — JavaScript refuses it; use '(?:' and accept that this group can backtrack.
1 | (?>a)b
| ^EDGE CASE. An atomic group is ordinary syntax in PCRE, Perl and .NET, and JavaScript has none — so the answer is a refusal naming the dialect and the offset, not a guess at what you meant. The caret frame points at the character the reader stopped on.
Every example on this page is executed against the same engine that powers the tool, on every build.
Gotchas worth knowing
The u flag changes the answer, not just the strictness
Without u, JavaScript accepts web-compatibility syntax that the same engine rejects the moment you add the flag: a bare brace read as a literal, a lone closing bracket, \8 with no eighth group, a legacy octal escape. Each earns a note naming the behaviour, because one letter in the flag box changes the answer.
A capture can exist and still be undefined
When a group sits inside something optional — a ? or a branch the match can skip — it is still numbered, but the match may finish without it ever participating. The reader marks those groups, so code doing groups[2].trim() downstream is not surprised at three in the morning.
Structure is read, behaviour is not judged
A note saying a quantified part can match the empty string describes the shape of the pattern. It is not a verdict on whether the pattern suits your data, and it is no claim about speed: a pattern that backtracks badly can hang a tab, and checking that against real input is the regex tester's job.
Common errors
Position 1: '(?>' is an atomic group, which exists in PCRE, Perl and .NET but not in JavaScript — JavaScript refuses it; use '(?:' and accept that this group can backtrack.- Patterns travel between languages faster than their syntax does. Atomic groups, possessive quantifiers, inline comments (?#…) and recursion (?R) belong to other engines; JavaScript refuses them, so the reader does too and names the family they came from.
Position 1: this '(' is never closed — JavaScript refuses the whole pattern; add the matching ')', or write it as \( to match a literal bracket.- One unbalanced bracket invalidates the entire pattern — there is no partial reading, here or in your program. The message carries the offset and a caret frame so the fix lands on the right character.
The u and v flags cannot be used together — v is the newer of the two and already implies Unicode mode. Keep one of them.- The two Unicode modes are mutually exclusive by specification: v is a superset that adds set notation and properties of strings, so asking for both is refused before any parsing starts. Unknown or repeated flag letters are rejected the same way.
This pattern is 5000 characters and the reader stops at 4096. Nothing was parsed; shorten the pattern, or download the state file and split it.- The reader has three hard bounds and prints the one it hit: 4096 characters of pattern, 50 levels of nesting, 5000 parts. Nothing is parsed past a refusal, and the message states the real number rather than a vague apology.
FAQ
Which engine's rules is this reading, and can a browser disagree?
The rules are ECMAScript's, and the accept/reject behaviour was pinned against V8 — the engine inside Chrome, Edge and Node. Safari and Firefox differ at the edges, mainly around v-flag set notation. Whether the flags you ticked are supported is read from the browser you are using right now.
Does the explanation tell me whether my pattern is correct?
No, and nothing here pretends otherwise. This page tells you what the pattern says — which characters it accepts, what each group keeps, where a quantifier stops. Whether that suits your data is a question only your data answers, which is what the sample-text box is for.
What happens to a pattern written for Python, Go or .NET?
The parts JavaScript shares are read normally; the parts it does not have are called out by name. Some are outright refusals with the offset marked. Others are quieter: without the u flag, \A and \z are not errors in JavaScript at all — they match the plain letters A and z — so the reader raises a note instead.
Keyboard shortcuts
- ⌘/Ctrl + Enter
- Run the pattern against the sample text in the worker.
- ⌘/Ctrl + S
- Download the explanation as a .json file.
- ⌘/Ctrl + C
- Copy the explanation when no text is selected.
- ⌘/Ctrl + Shift + C
- Copy the explanation even over an active selection.
- t
- Switch to the next theme.
- ? or ⌘/Ctrl + /
- Open the keyboard-shortcut reference.
- Esc
- Close the topmost overlay and return focus.