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

FlagEffect
gFind every match rather than stopping at the first.
iCase-insensitive matching.
mMakes ^ and $ match at every line break instead of only at the start and end of the whole string.
sMakes . match newlines, which it otherwise never does.
uFull 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.

Other tools