regex / tester

Regex Tester

Build a regular expression and watch it match against your test string in real time, with every match highlighted and listed. Includes a quick reference for the syntax.

~/regex/testerEnter a pattern
/ /
Flags g global i ignore-case m multiline s dotall
Test string
Matches highlighted
// matches

No matches yet.

reference

Regex cheat sheet

The pieces you reach for most often. Combine them to describe a pattern, then test it above:

TokenMatchesTokenMatches
\da digit 0–9.any char (except newline)
\wletter, digit or _*0 or more
\swhitespace+1 or more
^ $start / end?0 or 1 (or lazy)
[a-z]a character range{2,4}2 to 4 times
(…)a capture groupa|ba or b

Gotcha — runaway backtracking. Patterns with nested quantifiers like (a+)+$ can take seconds or minutes on certain inputs, freezing whatever runs them. Keep quantifiers from overlapping, anchor where you can, and prefer specific classes over .*. Also remember . doesn't cross newlines unless you add the s flag.

flags

The flags that change everything

A pattern's behaviour depends as much on its flags as on the tokens:

FlagEffect
gGlobal — find every match, not just the first
iCase-insensitive
mMultiline — ^ and $ match at each line
sDotall — . also matches newlines

Greedy vs. lazy

Quantifiers are greedy by default: .* grabs as much as possible, which is why <.*> on <a><b> matches the whole string instead of just <a>. Add a ? to make them lazy<.*?> stops at the first >. Getting this wrong is the usual reason a pattern "matches too much".

Don't validate email with a giant regex. The "perfect" email pattern is thousands of characters and still wrong. A loose check like /^\S+@\S+\.\S+$/ plus an actual confirmation email beats trying to encode the full spec in a pattern.

groups

Capturing, naming and reusing parts of a match

Parentheses don't just group — they capture. (\d{4})-(\d{2})-(\d{2}) against a date gives you the year, month and day as groups 1, 2 and 3, which you can pull out or reference in a replacement as $1, $2 and so on. Once a pattern has more than two groups, positional numbers get hard to read, so name them: (?<year>\d{4}) lets you ask for the year group by name instead of counting parentheses. Backreferences go the other way and match something you already captured — (['"]).*?\1 matches a quoted string and insists the closing quote is the same character as the opening one, which a plain ['"] on each end wouldn't.

danger zones

Catastrophic backtracking, and when not to use regex at all

A regex can hang a server. Patterns with nested, overlapping quantifiers — the textbook example is (a+)+$ — can take exponential time on an input that almost matches, freezing whatever runs them. This isn't theoretical; "ReDoS" has taken down real services and shown up in published CVEs, often hiding in an innocent-looking validation regex. JavaScript and PCRE are both vulnerable because they backtrack; Go and Rust use RE2, which guarantees linear time by giving up some features. Keep quantifiers from overlapping, anchor where you can, and be suspicious of any pattern that nests + or *.

The other lesson is knowing when to put the regex down. People reach for it to parse HTML, JSON or CSV, and it bites them every time, because those formats nest and escape in ways a regular expression fundamentally can't track. Use a real parser for structured formats and save regex for what it's good at: finding and pulling out patterns in flat text.

faq
Does JavaScript support named capture groups?

Yes, since ES2018. Write (?<year>\d{4}) and read it back as match.groups.year, which is far clearer than counting parentheses for match[1]. Older engines and some other flavours differ, so test in the environment you'll ship in.

What is "catastrophic backtracking" (ReDoS)?

Certain patterns with nested quantifiers like (a+)+ take exponential time on near-matching input, which can freeze the program running them — a denial-of-service risk. Avoid overlapping quantifiers and anchor your patterns; engines like RE2 (Go, Rust) avoid it by design.

Can I parse HTML or JSON with a regex?

You shouldn't. Those formats nest and escape in ways a regular expression can't reliably handle. Use a proper parser for structured data and keep regex for matching patterns in flat text.

Why does my pattern match more than I expected?

Almost always a greedy quantifier. .* grabs as much as it can; add a ? to make it lazy (.*?) so it stops at the first possible match.

How do I match a literal dot or question mark?

Escape it with a backslash: \. for a dot, \? for a question mark. Unescaped, those characters have special meaning.

Which regex flavour is this?

JavaScript's (ECMAScript) RegExp, the same engine your browser and Node use. Most patterns are portable, but lookbehind and named groups vary across languages.

How do I match across lines?

Use the m flag so ^ and $ match at each line break, and the s flag so . also matches newlines.

Is my test text private?

Yes. The pattern runs against your text entirely in the browser; nothing is sent anywhere.