Skip to content
R3XTools

Regex Tester

Run a JavaScript regular expression against sample text and inspect every match.

Regular expression

g

Test string

Paste the text to match against

Matches are highlighted as you type

Chars
0
Lines
0

Matches

Enter a pattern to see matches.

Quick reference

  • .Any character except a line break
  • \d \w \sDigit, word character, whitespace
  • \D \W \SThe negation of each
  • [abc] [^abc]One of the set, or anything but the set
  • a? a* a+Zero or one, zero or more, one or more
  • a{2,4}Between two and four times
  • a+?Lazy: match as few as possible
  • ^ $Start and end of input (or line with m)
  • \bWord boundary
  • (abc)Capture group
  • (?:abc)Group without capturing
  • (?<year>\d{4})Named capture group
  • (?=abc) (?!abc)Lookahead: followed by, not followed by
  • (?<=abc) (?<!abc)Lookbehind: preceded by, not preceded by
  • a|bEither alternative

Processed locally in your browser. Patterns run in a Web Worker in this tab. Your pattern and test string are never sent anywhere, and are never evaluated as code.

Reference

Which engine this is

Patterns are compiled with JavaScript's own RegExp, so what you see here is exactly what your browser or Node will do. That matters, because regular expression dialects differ: PCRE, RE2, Python's re and POSIX all disagree about lookbehind, atomic groups, possessive quantifiers and named-group syntax. A pattern that works here may not work in Go or in a database.

Flags

FlagEffect
gFind every match. Without it, only the first is returned.
iCase-insensitive matching.
m^ and $ match at line breaks as well as string boundaries.
sLets . match newlines.
uUnicode mode: \u{1F600} escapes work and surrogate pairs are one unit.
ySticky: matches only at lastIndex, never searching forward.

Capture groups

Numbered groups are counted by opening parenthesis, left to right. A group inside an alternative that did not participate in the match reports undefined rather than an empty string — the distinction matters when you are testing whether a branch was taken. Use (?:…) when you need grouping without a capture, and (?<name>…) when the position would be fragile.

Catastrophic backtracking

Some patterns take exponential time on input that almost matches. The classic shape is a repeated group that itself repeats, such as (a+)+$: the engine has an exponential number of ways to divide the a's between the two quantifiers, and it tries all of them before concluding there is no match.

This page flags those shapes before running them, and executes every pattern in a Web Worker with a 1.2-second deadline — if the deadline passes, the worker is terminated rather than left to spin. The same failure in a request handler takes down the process, which is why it has a name: ReDoS.

Where regex is the wrong tool

Nested structures — HTML, JSON, source code, balanced brackets — cannot be matched by a regular expression, because they are not regular languages. A pattern that appears to work on your sample will fail on the first nested case. Parse those with a parser.

Questions

Which regex flavour does this use?
JavaScript's, exactly as it runs in your browser. Patterns that work here work in Node and in the browser. PCRE, Python and Go differ in lookbehind support, named group syntax and some character classes, so a pattern that passes here is not guaranteed elsewhere.
Why did my pattern freeze the page?
It did not — patterns run in a Web Worker with a deadline, and the worker is terminated if it is exceeded. That happens with catastrophic backtracking, usually from nested quantifiers like (a+)+. The tool warns about that shape before you run it.
What does the g flag change?
It makes the regex find every match instead of stopping at the first, and it makes the regex object stateful — lastIndex persists between calls, which is a classic source of a pattern that works once and then fails. This tool resets state between runs so what you see is what a fresh regex would do.