Developer Tools· 5 min read

Regex Tester: Understanding Flags, Groups, and the g-Flag Trap

See exactly what each JavaScript regex flag changes, and why the global flag alone breaks naive match loops.

By EasyDevTools Team Last updated: 2026-08-24

The same pattern, six different behaviors depending on the flags

A regex pattern by itself is incomplete — the flags attached to it fundamentally change what it matches and how. `/foo/` and `/foo/gi` aren't the same search with different verbosity; they're different matching behaviors entirely. This tool uses JavaScript's native RegExp engine — the same one running in your browser's JavaScript and in Node.js — so whatever pattern and flag combination works here will behave identically in real code, which is exactly the point of testing against a live engine rather than a simplified regex simulator.

See it in action

What each flag actually changes

FlagNameEffect
gGlobalFinds all matches instead of stopping at the first
iCase-insensitiveIgnores letter case when matching
mMultiline`^` and `$` match line boundaries, not just string start/end
sDotall`.` matches newline characters too
uUnicodeEnables full Unicode code point matching (important for characters outside the basic multilingual plane)
yStickyMatches only starting at the exact lastIndex position, not anywhere later in the string

Testing a pattern

Enter your regex pattern (without the surrounding slashes).

Toggle the flags you need: g, i, m, s, u, y.

Type or paste the text to test against.

Review the highlighted matches and the per-match group table.

The g-flag bug that trips up real code

This is worth understanding even outside this tool, because it's a genuine JavaScript gotcha: when a RegExp has the `g` flag, calling `.exec()` repeatedly on the same regex object advances an internal `lastIndex` property, so each call picks up where the last one left off. This is how you get all matches in a loop — but it also means calling `.exec()` on a `g`-flagged regex just once, expecting it to behave like a non-global match, returns only the first result and silently leaves `lastIndex` in a non-zero state for the next call.

If you've ever seen a `g`-flagged regex `.match()` or `.exec()` mysteriously return only one result outside of a loop, this internal `lastIndex` state advancing is almost always why. This tool handles that internally so the match list you see here always reflects every match in your input, regardless of how the underlying exec loop works.

Reading the capture group table

Each match shown includes its capture groups as an ordered list matching the order your parentheses appear in the pattern. A group defined with `?` for optionality — like `(a)?` — can legitimately not participate in a given match, and when that happens, the tool shows `(undef)` rather than an empty string, which matters: `undefined` and `''` are genuinely different values in JavaScript, and code relying on `match[1] === undefined` to detect a non-participating group would break if the tool silently substituted an empty string instead.

Common mistakes

Forgetting the `g` flag and being confused why only one match highlights, when the pattern is otherwise correct.

Using `.` expecting it to match newlines by default — it doesn't, unless the `s` (dotall) flag is set.

Assuming `^` and `$` anchor to the whole string when testing multi-line input — without the `m` flag, they only match the very start and end of the entire string, not each line.

Writing a pattern with unbounded repetition against ambiguous input (like nested quantifiers) that can produce catastrophic backtracking — if matches seem to hang or the 5,000-match cap kicks in unexpectedly, the pattern itself may need restructuring.

Why there's a 5,000-match cap

Certain regex patterns — particularly zero-width matches, like a lookahead with no actual character consumption — can technically match an unbounded number of times against ordinary input, which would freeze the page trying to enumerate them all. Capping at 5,000 matches per test run keeps the tool responsive even against a pathological pattern, while still being far more than enough to validate a pattern's correctness against realistic test text.

Real use cases

Validating an email or phone-number pattern against a batch of sample inputs before shipping it in form validation code.

Debugging why a production regex isn't matching expected text, using live highlighting to see exactly what it does match.

Extracting structured data from log lines using capture groups, and confirming the group order before writing the parsing code.

Testing a find-and-replace pattern's matches before running it against a large codebase or dataset.

Frequently asked questions

Q: Which regex flavor does this use?

A: JavaScript's native RegExp — the same engine that runs in your browser and in Node.js. Patterns that work here will work identically in your JS code.


Q: What does each flag mean?

A: g = global (all matches), i = case-insensitive, m = multiline (^/$ match line boundaries), s = dotall (. matches newlines), u = unicode, y = sticky.


Q: Why does my regex with the g flag return only one match elsewhere?

A: With the g flag, `RegExp.exec()` and `.match()` advance an internal `lastIndex` property between calls. This tool handles that internally so you always see every match in the input, regardless of how a manual exec loop is written.


Q: Can I see capture groups?

A: Yes — each match row shows all capture groups as an ordered list. Groups that didn't participate in a match, such as from `(a)?` not matching, show `(undef)`.


Q: Is there a match limit?

A: The tool caps at 5,000 matches per test to prevent runaway patterns, like zero-width matches, from freezing the page.


Q: Why doesn't `^` match the start of every line in my multi-line text?

A: By default, `^` and `$` only anchor to the start and end of the entire input string. Enable the `m` (multiline) flag to have them match at each line boundary instead.

Test your pattern now

Try your regex on the Regex Tester. Validating structured data instead? Check the JSON Formatter. Working with encoded text? Try URL Encode / Decode or Base64 Encode / Decode.

Need help using this tool?

Read our complete Regex Tester tutorial for step-by-step guidance.

Ready to try the tool?

No accounts. No uploads. No limits. Start now.