Regex Tester & Explainer

Write a regular expression, watch every match and capture group light up in your own text, and read a line-by-line breakdown of what the pattern does.

How it works

The pattern goes between the slashes and the flags are the chips beneath it. The slashes and flag letters are drawn by the page, so what you type is the pattern alone, on one line. Every match in the text below is tinted, each capturing group in a colour of its own, with a legend naming the groups.

The search is the browser's own RegExp, so it is JavaScript's flavour exactly as your code will run it, run in a background worker so that a slow pattern cannot freeze the page. The explanation comes from a separate parser that takes the pattern apart line by line: each group with its number and name, each quantifier with its range and whether it is greedy or lazy, each class and escape in words. When the pattern will not compile, the engine's error is shown and nothing is painted.

All eight flags are offered: g, i, m, s, u, v, y and d. The u and v flags cannot be combined, so turning one on turns the other off. A search stops at 5,000 matches and says so.

Examples

Dates with named groups

The pattern the page opens with, with g set, against its four sample lines:

(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})

Three matches: 2024-01-15, 2024-02-29 and 2025-12-31, with 20240115 on the third line left alone for having no hyphens. The explanation begins:

(?<year>\d{4})  Capturing group 1, named year
  \d{4}  Repeat exactly 4 times — greedy, giving back only if the rest fails
    \d  A digit — 0 to 9
-  Literal character

Greedy, lazy and a negated class

<b>bold</b> and <i>italic</i>

Three patterns against that line, with g set:

<.+>     1 match    <b>bold</b> and <i>italic</i>
<.+?>    4 matches  <b>  </b>  <i>  </i>
<[^>]+>  4 matches  <b>  </b>  <i>  </i>

The greedy .+ runs to the end of the line and gives back characters only until a > follows. The lazy .+? takes as little as it can. The negated class finds the same four without backtracking at all, since it cannot run past a > in the first place.

An emoji is two characters without u

^.$ against 😀 finds no matches: without a Unicode flag the engine reads UTF-16 code units, and U+1F600 is two of them. With u or v set it finds 1 match, the emoji.

Common problems

The search is stopped because the pattern backtracks too much

Catastrophic backtracking. ^(a+)+$ against a run of a ending in ! fails only after trying every way of dividing the run between the two quantifiers, and that number doubles with each a. The search runs in a worker of its own, so the page and its editors keep working while it runs; after a second it is stopped, nothing is highlighted, and the page says the pattern backtracks too much on this text. A server has no such limit and would hang on it. Nested quantifiers over the same characters are the thing to remove; ^a+$ gives the same answer at once.

^ and $ match nothing in a multi-line text

Without m they match only at the very start and end of the text, so ^\w+$ against one and two on separate lines finds nothing; with m it finds both. Likewise . stops at a line break unless s is set, and without g or y the search stops at the first match.

A pattern from Python or PCRE does not work

JavaScript has no Python-style named group, possessive quantifier or atomic group, so none of these compiles:

(?P<year>\d{4})
a++
(?>a+)

A JavaScript named group drops the P. Worse is \A: without u it is an escaped A, so \Aabc matches the text Aabc. With u or v set it is an error instead, which is one reason to set one.

Frequently asked questions

How do I use the pattern in code?

Write it between slashes with the flags after, /\d{4}-\d{2}/g, or pass it as a string, new RegExp("\\d{4}-\\d{2}", "g"), where every backslash is doubled because the string literal consumes one. The box takes the pattern as it would appear between the slashes, so paste from a literal, not from a string.

What is the difference between the u and v flags?

Both read the pattern by code point and allow \p{…} property escapes. The v flag adds set operations inside classes: [\p{L}--[a-z]] is any letter except a to z, and && intersects. A pattern cannot have both, which is why the chips treat them as one switch.

Why does the count include matches I cannot see?

A pattern that can match nothing, such as x*, matches the empty string at every position where there is no x: against ab with g that is 3 matches. They are counted, but an empty match has no text to tint.

Can I test Python regular expressions here?

No. The engine is the browser's JavaScript one, and Python's re differs in syntax and in details such as named groups. The Python page runs Python and its standard library in the browser, where re can be tried directly.

Related tools

References