Regex Tester
Test JavaScript regular expressions with highlighted matches, capture groups, a plain-English explanation, ready-made code and a catastrophic-backtracking check.
Cheatsheet
| Characters | |
|---|---|
| . | Any character except a line break; with the s flag, line breaks too |
| \d \D | A digit 0-9; \D is anything that is not a digit |
| \w \W | A letter, digit or underscore; \W is anything else |
| \s \S | A space, tab or line break; \S is anything that is not whitespace |
| [abc] | Any one of the listed characters |
| [^abc] | Any character that is not listed |
| [a-z] | Any character in the range |
| \. \+ | A backslash makes a special character literal |
| How many | |
| * | Zero or more |
| + | One or more |
| ? | Zero or one: the part before it is optional |
| {2} {2,} {2,5} | Exactly 2, at least 2, between 2 and 5 |
| +? *? | A ? after a quantifier makes it lazy: as few characters as possible |
| Groups and choices | |
| (…) | Capturing group, read back as $1, $2 … |
| (?:…) | Group without capturing |
| (?<name>…) | Named group, read back as $<name> |
| a|b | Either side of the bar |
| \1 | Whatever the first group matched, again |
| (?=…) (?!…) | Followed by / not followed by, without consuming it |
| (?<=…) (?<!…) | Preceded by / not preceded by, without consuming it |
| Positions | |
| ^ | Start of the text; with the m flag, start of a line |
| $ | End of the text; with the m flag, end of a line |
| \b \B | A word boundary; \B is anywhere that is not one |
| Flags | |
| g | Find every match, not only the first |
| i | Ignore upper and lower case |
| m | ^ and $ also match at each line break |
| s | The dot also matches line breaks |
| u v | Unicode mode, needed for \p{…}; v is the extended form |
| y | Sticky: match only where the last match ended |
| d | Report the start and end of every group, shown in the match table |
Related tools
- Text UtilitiesCount words and characters, change case and turn titles into URL slugs.
- JSON ToolsFormat, minify, repair and validate JSON with exact error positions, browse it as a tree, and convert between JSON, CSV and YAML.
- Code FormatterFormat and minify XML, HTML and CSS, and minify JavaScript, in your browser.
About this tool
Regex Tester runs a JavaScript regular expression against your sample text as you type: matches are highlighted in place, and a table lists every match with its index and its capture groups, named ones included. Turn on Replace to see the result of String.replace with $1, $<name> or $& in the replacement. Explanation reads the pattern back to you part by part - “exactly 4 of a digit 0-9”, “a capture group named year”, “a word boundary” - and says so plainly for any construct it does not recognise instead of describing it from a guess. Use this pattern in code turns the same pattern and flags into a JavaScript, Python, PHP or Go snippet, with each language’s flag spelling and a note for every flag that language has no counterpart for. The backtracking check reads the same parse for the shapes that cause catastrophic backtracking - a quantifier nested in a quantifier over characters they share, alternatives that can match the same text under a quantifier, and an unbounded repetition followed by something that can match the same characters - and names the substring, why it backtracks and a rewrite; it never runs the pattern against input built to be slow, so it can tell you it found a shape but never that there is none. It is the JavaScript engine, so PCRE-only syntax such as recursion, atomic groups or possessive quantifiers is not available, and it tests patterns rather than validating data formats for you.
The pattern, the flags, the test text and the replacement never leave your browser: they are evaluated in a Web Worker, are not sent to the XGM API and are not written into the URL, so a link you share carries the tool and nothing you typed. The worker is terminated after 1.5 seconds, which is why a pattern with catastrophic backtracking stops the run instead of freezing the page. The explanation, the code snippets and the backtracking check are built from the pattern text in the page as well: all three parse the pattern rather than running it, and each says so for anything it does not recognise instead of describing it from a guess. The backtracking check in particular never tries the pattern against input built to be slow - it looks for the shapes that backtrack - so it can only tell you that it found one, never that there is none.
How to use it
- Open the Regex Tester tool.
- Paste or type the input you want to inspect.
- Read the result, which is computed in your browser; the input is not sent to XGM.
- Copy the output only after checking it looks correct.
- Use related XGM tools if you need a broader diagnostic view.
FAQ
Which flags can I use?
g, i, m, s, u, y, d and v - the flags of the browser's own RegExp. Without g only the first match is returned; s lets a dot match newlines; d adds the start and end index of each capture group.
Why did the tester stop after 1.5 seconds, and does it check my pattern for ReDoS?
The pattern ran into catastrophic backtracking, usually nested quantifiers such as (a+)+ or (\w+\s?)* against text that almost matches. It runs in a Web Worker that is terminated at 1.5 seconds, so the page stays responsive - a server running the same pattern on user input has no such guard. The backtracking check reads the shape of the pattern without running it against input built to be slow, and reports three structures with the exact substring: a quantifier nested inside another over characters they share, a quantified group whose alternatives can match the same text, and an unbounded repetition followed by something that can match the same characters. Each one names why it backtracks and how to rewrite it. A construct it cannot parse is reported as “not analysed” rather than safe, and a clean result is not a proof.
Does my pattern or test text leave the browser?
No. Everything runs in a Web Worker in your browser, nothing is sent to the XGM server, and the URL keeps only the tool, never your pattern or text.
Why do I only see the first 200 matches?
Highlighting stops at 300 matches and the table at 200, to keep rendering fast on large inputs. The counter above them shows the real total with a + when it was capped, and the JSON export contains the full result.
Why does my pattern behave differently in Python or PHP?
Escapes and classes differ between engines: \d is Unicode-aware in Python 3 but ASCII-only in JavaScript without the u flag, lookbehind is not available everywhere, and named groups use (?P<name>) in Python against (?<name>) here. Test with the engine that will run the pattern in production.
How accurate is the plain-English explanation?
It parses the pattern itself - it never runs it - and describes anchors, escapes, character classes with their ranges, groups (capturing, named, non-capturing and all four lookarounds), backreferences, alternation and every quantifier including the lazy ones, with the m and s flags folded into what ^, $ and the dot are said to mean. Anything outside that, such as an inline modifier group like (?i:…) or the set operations the v flag allows inside brackets, is shown exactly as you wrote it and labelled “Not explained”, because a wrong explanation is worse than none.
Do the generated snippets run as they are?
They are the compile-and-match skeleton for each language, over a text variable you supply. Flags are translated rather than copied: Python gets re.IGNORECASE, re.MULTILINE and re.DOTALL, PHP gets i, m, s and u after the delimiter, and Go gets them inside the pattern as (?ims). g has no letter outside JavaScript, so the snippet uses finditer, preg_match_all or FindAllStringSubmatch instead, and y, d and v have no counterpart anywhere and are named in a note rather than dropped in silence. Two more notes appear when they apply: Python spells a named group (?P<name>…), and Go's RE2 engine rejects lookaround and backreferences outright.