How to Test and Debug a Regular Expression

Test and debug regular expressions the practical way — understand flags, capture groups and greedy matching, and fix patterns that almost work.

Updated 6 min read By CodingEagles
Free tool Regex Tester Test regex live with match highlights, groups and a cheatsheet. Open tool

A regular expression that “almost works” is one of the most common time sinks in programming. The fix is usually small — a flag, a lazy quantifier, an escaped character — but spotting it is much easier when you can see matches highlighted live.

This guide covers the flags, groups and quantifiers that matter, and how to debug a pattern that isn’t behaving.

TL;DR — Paste your pattern and test text into the regex tester, toggle flags, and watch matches highlight as you type. Use lazy quantifiers (*?, +?) when a match grabs too much.

Flags change everything

Flags are the modifiers after the pattern. The ones you’ll use most:

  • g — global: find all matches, not just the first.
  • i — case-insensitive.
  • m — multiline: ^ and $ match at line breaks.
  • s — dotall: . also matches newlines.
  • u — unicode: correct handling of code points and \p{...} classes.
  • y — sticky: match only at the current position.

Many “it doesn’t find all of them” bugs are just a missing g, and many “it stops at the first line” bugs are a missing m.

Greedy vs. lazy matching

By default, * and + are greedy — they match as much as they can and then back off. So <.*> against <a><b> matches the whole <a><b>, not just <a>. Add ? to make them lazy: <.*?> matches <a> and <b> separately. This single character fixes a huge share of “it matched too much” problems.

Capture groups

Parentheses create capture groups, which let you extract parts of a match:

(\w+)@(\w+\.\w+)

Against dev@example.com, group 1 is dev and group 2 is example.com. Use named groups for readability — (?<user>\w+)@(?<domain>\S+) — and reference them by name instead of number. The tester lists every group per match so you can confirm you’re capturing the right spans.

Escape the special characters

Characters like ., *, +, ?, (, ), [, ], {, }, ^, $, | and \ have special meaning. To match them literally, escape with a backslash: \. matches a real dot, not “any character”. Forgetting this is why 3.14 unexpectedly matches 3x14.

Debug it live

The fastest way to fix a stubborn pattern is to build it up incrementally and watch the highlights. Start with the simplest version that matches something, then tighten it one token at a time in the regex tester — it uses the same JavaScript engine as your browser and Node, so what you see is exactly what your code will do.

Frequently asked questions

Why does my regex match too much?
Quantifiers like * and + are greedy — they grab as much as possible. Make them lazy with a trailing ? (for example .*? instead of .*) so they match the shortest span.
What does the g flag actually do?
The global flag makes the engine find every match rather than stopping at the first. Without g, methods like match return only the first result and its groups.
How do I match across multiple lines?
Use the m flag so ^ and $ anchor to line starts and ends, and the s flag so . also matches newline characters when you need it to span lines.

Ready to try it?

Test regex live with match highlights, groups and a cheatsheet. Free, in-browser, and 100% private — your data never leaves your device.

Open the Regex Tester