Regex Bench › Regex Tester
Regular Expression Tester
Type a pattern and some sample text. Matches highlight as you type, every capture group is listed, and the replace box previews the result before you commit to it.
● Runs locally. What you paste never leaves this page.
The flags, and what each actually changes
| Flag | Effect |
|---|---|
g | Find every match rather than stopping at the first. |
i | Case-insensitive matching. |
m | Makes ^ and $ match at every line break instead of only at the start and end of the whole string. |
s | Makes . match newlines, which it otherwise never does. |
u | Full Unicode mode. Needed for \p{...} property escapes and for correct handling of characters outside the Basic Multilingual Plane. |
The m and s flags are the two that most often
explain a pattern behaving unexpectedly. If a pattern works on one line and
fails on a multi-line document, one of them is usually the answer.
Greedy and lazy quantifiers
By default quantifiers are greedy: they consume as much as possible and then
give characters back until the rest of the pattern can match. So
<.+> against <a>text</a> matches
the entire string, not just the first tag, because .+ takes
everything and then backtracks to the final >.
Adding ? makes a quantifier lazy, so it takes as little as
possible. <.+?> matches just <a>. This
single character is the fix for a large share of "my regex matched too much"
problems.
Capture groups
Parentheses capture. Each group is numbered from left to right by the
position of its opening bracket, and is available in a replacement as
$1, $2 and so on. Named groups, written
(?<name>...), are clearer in anything you intend to keep, and
are referenced as $<name>.
Use (?:...) when you need grouping for alternation or
quantification but do not want a capture. This keeps your group numbers stable,
which matters because inserting one capturing group early in a pattern silently
renumbers everything after it and breaks the replacement.
Catastrophic backtracking
Some patterns take exponential time on input that nearly matches. The classic
shape is a quantifier inside another quantifier where both can match the same
characters, such as (a+)+$. Against a long run of "a" followed by
one "b" the engine explores an enormous number of ways to divide the text before
concluding there is no match.
This is a real denial-of-service vector when a pattern runs against user
input on a server. Avoid nesting quantifiers over overlapping character sets,
prefer explicit character classes to .*, and anchor patterns where
you can. Matching here is capped so the page cannot hang, but a pattern that
feels slow in the browser will be dangerous on a server.
Flavours differ
This tester uses the JavaScript engine, which is what runs in browsers and Node. Most syntax is shared across languages, but lookbehind support, possessive quantifiers, atomic groups and some Unicode property names vary between JavaScript, PCRE, Python and Go. A pattern verified here will behave identically in JavaScript, and almost always in other engines, but verify anything exotic in its destination.
Questions
Why does my pattern match more than I expected?
Quantifiers are greedy by default, so .+ takes as much as it can before backtracking. Add a question mark to make it lazy, as in .+?, so it takes as little as possible.
Why does the dot not match my newline?
By design. The dot excludes line terminators unless the s flag, sometimes called dotall, is enabled. Turn on s when your pattern needs to span lines.
What is the difference between the m flag and the s flag?
The m flag changes what the anchors mean, so caret and dollar match at each line break. The s flag changes what the dot matches, allowing it to include newlines. They are independent and often confused.
When should I use a non-capturing group?
Whenever you need parentheses only for grouping. Non-capturing groups written with question mark colon keep your numbered groups stable, so adding a group later does not renumber the references in your replacement.
Which regex flavour does this use?
JavaScript's, which is what browsers and Node run. Core syntax is shared with other languages, but lookbehind, atomic groups and some Unicode properties differ, so verify unusual constructs in the engine you will deploy to.