Loading…
Loading…
Test regex live — railroad diagrams + plain English explained
| # | Match | Position |
|---|---|---|
| 0 | [email protected] | 14 |
| 1 | [email protected] | 33 |
one or more of any character in [a-z], then "@", then one or more of any character in [a-z], then ".", then 2 or more of any character in [a-z] Flags: global (find all matches)
Run your projects on Claude Code?
We packaged the .claude config that runs this site — 26 specialist agents, 14 workflow skills, and 6 rule files from 31 real production incidents. From $9.
Get the Claude Code Production Pack — $29JavaScript's RegExp engine (ECMAScript) supports named capture groups, lookbehind and Unicode property escapes, all added in ES2018. It is the same engine in browser JavaScript and Node.js. A playground that renders railroad diagrams turns an abstract pattern like /^(?=.*[A-Z])(?=.*\d).{8,}$/ into a flowchart you can read box by box: the two lookaheads are drawn as zero-width checks at the start of the string, and only .{8,} consumes text. The replace preview shows what a substitution produces before it ships.
Pattern matching runs the browser's native RegExp engine, the same ECMAScript engine your browser runs JavaScript with. With the g flag the playground collects every match through String.prototype.matchAll (stopping at 1,000 matches); without g it shows the first match only, as RegExp.prototype.exec does. Matches highlight as you type, and the replace field previews String.prototype.replace with your replacement string.
Railroad diagrams are generated by parsing the pattern into an AST (abstract syntax tree) and rendering each token — literals, character classes, quantifiers, groups, alternation — as connected boxes where left-to-right flow is the matching direction. Node types are color-coded: blue for literals, green for character classes, purple for groups, teal for zero-width lookarounds, orange for quantifiers and red for anchors.
The plain English explainer walks the same AST and writes a description for each node. The pattern \b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b is explained as: a word boundary, then one or more of any character in [A-Z0-9._%+-], then "@", then one or more of any character in [A-Z0-9.-], and so on.
"Copy link" writes the pattern, flags, test string and replacement into the URL's # fragment (the shared state is capped at 8,000 encoded characters), so a shared link reopens the same state. Browsers do not send the fragment to the server, so shared test data never reaches server logs or analytics. A shared link loads paused and runs only when you click "Run shared pattern".
A developer writing an email validation function tests their pattern against a list of edge-case strings to verify it rejects missing TLDs but accepts plus-sign subaddresses.
A developer renaming log fields previews a replacement like $<key>=$<value> on sample lines before running it across the codebase.
A data engineer crafts a regex to extract ISO 8601 timestamps from messy log lines, checking the match table's group column to confirm the optional milliseconds group captures when present and shows '-' when absent.
A security engineer builds an input sanitization pattern and uses the explainer to document it in plain English for a code review comment.
A junior developer learning regex uses the railroad diagram to understand how alternation and grouping interact in an existing pattern they inherited.
Scope note: Matching uses your browser's JavaScript (ECMAScript) engine, so results can differ from PCRE, Python re, Go RE2 or Java — for example RE2 has no backreferences or lookbehind, and possessive quantifiers are not supported in JavaScript. A pattern that is fast on short test strings can still backtrack catastrophically on long or hostile input; test worst-case inputs before using a pattern on untrusted data.
Type your regex pattern and toggle flags (g, i, m, s, u, v, y, d) — an invalid pattern or flag shows the engine error under the input
Enter a test string — matches highlight as you type and the table lists each match, its position and its capture groups
Type a replacement such as [$&], $1 or $<name> to preview the replaced text live
View the railroad diagram and the plain English explanation to read the pattern part by part
Click "Copy link" to share the pattern, flags, test string and replacement, or "Copy matches as JSON" to export the results
About the Regex Playground
JavaScript regex (ECMAScript). Matching runs your browser's own RegExp engine, the same flavor Node.js and browser JavaScript use.
A flowchart of your pattern read left to right: literals, character classes, groups, alternation branches and quantifier loops are drawn as connected boxes, so nested structure is easier to follow than in raw regex syntax. Lookaheads and lookbehinds get their own teal box labeled zero-width, for example "Negative lookahead (zero-width)": they check the text at that point without consuming any of it, so the next box starts at the same position.
Share by link. "Copy link" builds a URL that carries the pattern, flags, test string and replacement in the link's # fragment (#p=, &f=, &t=, &r=), which browsers never send to the server, so your test data stays out of server logs and analytics. Opening that URL loads the state back paused: nothing runs until you click "Run shared pattern", so a link with a catastrophically backtracking pattern cannot freeze your tab. The shared state in the link is capped at 8,000 encoded characters; if your input is longer, the test string is cut first (then the replacement, then the pattern) and a note says so. Non-ASCII text uses up that budget faster, since one Chinese character encodes to 9 characters. Nothing is stored on a server or in your browser — the link itself is the saved copy.
All eight: g (global — find every match), i (ignoreCase), m (multiline — ^ and $ match at line breaks), s (dotAll — . also matches newlines), u (unicode — match by code point, enable \p{…} escapes and stricter syntax), v (unicodeSets — everything u does plus set subtraction and intersection inside [...] and string properties such as \p{RGI_Emoji}; u and v cannot be combined, so turning one on turns the other off), y (sticky — match only at lastIndex, so with g the matches must be back to back from index 0) and d (hasIndices — report start and end offsets for the match and each group, shown in the match table). Flags combine freely; if a pattern is invalid under a flag (for example \p{L} is fine with u, but a lone { is a syntax error under u), the engine error appears under the input (per MDN, RegExp.prototype.flags).
The preview calls String.prototype.replace with your pattern, so it uses JavaScript's replacement patterns: $& inserts the whole match, $1 to $99 insert numbered groups, $<name> inserts a named group, $` and $' insert the text before and after the match, and $$ inserts a literal $. With the g flag every match is replaced (the same result as replaceAll); without g only the first match is. A group that did not take part in the match inserts an empty string (per MDN, String.prototype.replace).
Wrap the part of your pattern you want to extract in parentheses. The match table shows each capture group numbered from left to right, and named groups written as (?<name>…) are labeled with their name next to the number. "Copy matches as JSON" exports every match (up to the first 1,000) with its text, index and groups (plus named groups, and start/end offsets when the d flag is on).
It describes literals, character classes, shorthand classes such as \d and \w, anchors, capturing, named and non-capturing groups, backreferences (\1 and \k<name> read as "the same text group #1 matched"), character escapes (\0 as the NUL character, \xHH, \uHHHH, \cX and, with u or v, \u{…} and \p{…} property escapes; without u or v, \N with no group N reads as a legacy octal escape (or, for \8 and \9, the digit itself)), lookarounds ((?=…) reads as "followed by", (?!…) as "not followed by", (?<=…) as "preceded by" and (?<!…) as "not preceded by"), alternation and quantifiers (including lazy ones), in sequence. Group numbers match the match table, with named groups counted in order like any other capture. Under v, a class with nested classes or set operations, such as [\p{L}--[a-z]], is shown as one class exactly as written.
JavaScript's RegExp is a backtracking engine: when a match fails it retries every other way the quantifiers could have split the input. Nested quantifiers such as /^(a+)+$/ make that number of ways grow exponentially. Illustrative measurement in Node.js: testing that pattern against 20 a's followed by a b took about 5 ms, 22 a's about 19 ms, 24 a's about 77 ms, and 26 a's about 307 ms (median of 5 warm runs) — roughly doubling per extra character — while the equivalent /^a+$/ failed instantly. On a server this is a ReDoS risk. This playground runs your pattern in the page on every keystroke, so typing such a pattern against a long run of a's followed by a b can freeze this tab until you close it. Fix it by removing nested or overlapping quantifiers, making alternatives mutually exclusive, and limiting input length. Timings vary by machine.
Format, validate & diff JSON — runs entirely in browser
Open →DeveloperDecode JWT header, payload & expiry — tokens stay private
Open →SEO & ContentGenerate JSON-LD structured data for Google rich results
Open →DeveloperVisualize project dependencies as an interactive graph
Open →