Regex tester
Write a pattern, set your flags, and watch matches highlight live as you type — with capture groups broken out.
Test as you type
Regular expressions are famously hard to get right by reading alone — you really need to see them run. Enter a pattern and some test text and every match highlights instantly, with a running count and the contents of any capture groups listed below. Adjust the flags to change behaviour: g finds all matches, i makes it case-insensitive, m treats each line separately, and s lets the dot match newlines.
Building patterns with confidence
The fastest way to build a tricky pattern is incrementally: start broad, watch what matches, then tighten. Capture groups (the parts in parentheses) are shown separately so you can confirm you're extracting exactly the pieces you want — invaluable when you're using a regex for find-and-replace or pulling fields out of text. This uses your browser's own JavaScript regex engine, so what you see here is exactly how it'll behave in JavaScript code.
Greedy and lazy quantifiers
The single most common regex bug is a quantifier eating more than you intended. By default *, + and ? are greedy: they take as much as they can and give back only when forced. Run <.+> against <a>text</a> and you get one match spanning the whole string, not the two tags you expected.
Adding ? makes a quantifier lazy, taking as little as possible: <.+?> matches <a> and </a> separately. A more precise fix is often a negated character class such as <[^>]+>, which cannot cross a closing bracket at all and does not backtrack.
Escaping, and the characters that bite
Twelve characters carry special meaning and must be escaped with a backslash to match literally: . ^ $ * + ? ( ) [ ] { } | and the backslash itself. An unescaped dot is the usual culprit — example.com as a pattern happily matches examplexcom, because the dot means "any character".
- Inside a character class most of these lose their power, so
[.+]matches a literal dot or plus. - A
^immediately after[negates the class; anywhere else it is an anchor or a literal. - A
-means a range unless it is first or last in the class, so[a-z]is a range but[-az]is three literals.
Where regex is the wrong tool
Regular expressions match patterns in flat text. They are a poor fit for arbitrarily nested structures — HTML, JSON and source code all nest without limit, and a pattern cannot count how deep it currently is. Use a real parser for those.
Watch out too for catastrophic backtracking: nested quantifiers such as (a+)+$ can take exponential time on input that nearly matches, which is the basis of a whole class of denial-of-service bug. If a pattern is slow on long input, the fix is usually to make it more specific rather than to optimise around it. For a syntax refresher, the regex reference lists the tokens with examples.