Developer Regex tester
Test a regular expression against sample text with live highlighting, capture groups broken out, and replacement preview.
Written without the surrounding slashes.
/\b(\w+)@(\w+)\.(\w+)\b/g
Optional. Use $1, $2 for groups and $<name> for named groups.
- Matches
- 2
- Groups
- 3
- Flags
- g
Matches in context
Contact [email protected] or [email protected] for details.
| # | At | Match | Groups |
|---|---|---|---|
| 1 | 8 | [email protected] | $1=ada, $2=example, $3=com |
| 2 | 27 | [email protected] | $1=grace, $2=navy, $3=mil |
Ready. Runs locally on your device.

Your files stay on your device. The tool works directly in your browser, using your device to process your files. Nothing is sent to our servers, and we never receive, store, or see your files or figures.
Share result
Cite
Cite this page
Reembun. (2026, July 28). Regex tester. https://reembun.com/regex-tester
How to use it
Write the pattern
Without the surrounding slashes. It compiles as you type, and an invalid pattern says why.
Set the flags
g for every match, i to ignore case, m to make the anchors work per line, s to let the dot match newlines, u for unicode.
Paste the test string
Matches are highlighted in place, with every capture group listed underneath so you can see what each one caught.
Try the replacement
The Replacement box shows what a substitution would produce, using $1 and $2 to refer to groups.
Flags
| Flag | Effect |
|---|---|
g | Find all matches rather than stopping at the first |
i | Case insensitive |
m | ^ and $ match at line boundaries, not just string boundaries |
s | . also matches newlines |
u | Unicode mode; enables \p{...} property escapes |
The g flag has a side effect worth knowing: it makes a regex object stateful. Reusing the same global regex across calls without resetting lastIndex produces intermittent misses, and it is one of the most common bugs in JavaScript code that uses regular expressions.
Greedy versus lazy
This is the single most frequent cause of a pattern matching more than intended.
Input: <a>one</a> <a>two</a>
<a>.*</a> matches the whole string (greedy)
<a>.*?</a> matches <a>one</a> (lazy)
Greedy quantifiers take as much as they can and backtrack only when forced. Adding ? after *, +, ? or {n,m} makes them take as little as possible.
Capture groups
(\d{4})-(\d{2})-(\d{2})
Three numbered groups, available as $1, $2, $3 in a replacement.
Named groups are usually clearer:
(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})
Referenced as $<year> in a replacement, and far easier to maintain than positional numbers when the pattern changes.
Use (?:...) for a group you need for grouping but do not want to capture. It is marginally faster and keeps your numbering clean.
Common patterns
| Purpose | Pattern |
|---|---|
| Digits only | ^\d+$ |
| Word boundary | \bword\b |
| Trim whitespace | `^\s+ |
| Duplicate words | \b(\w+)\s+\1\b |
| HTML tag | <[^>]+> |
| Repeated blank lines | \n{3,} |
Where regex is the wrong tool
Parsing HTML. HTML is not a regular language. A pattern that works on your test input will fail on nested tags, attributes containing angle brackets, or comments. Use a parser: DOMParser in the browser is built in.
Validating email addresses. The RFC-compliant pattern is thousands of characters and still accepts addresses no mail server will deliver to. Check for an @ with something either side, then send a confirmation email. That is the only real validation.
Parsing JSON, CSV or code. All need a parser that understands nesting and quoting.
Catastrophic backtracking
Nested quantifiers over overlapping character classes can make matching time grow exponentially with input length:
(a+)+$ against aaaaaaaaaaaaaaaaaaaaaaaaaaX
This hangs. If a regex runs on untrusted input, such as a search box, a log parser or a validation rule, a pattern like this is a denial-of-service vulnerability, and it has taken down production systems at several large companies. Avoid nesting quantifiers, and prefer explicit character classes over . wherever you can.
Common questions
Which regex flavour is this?
JavaScript's, which is what runs in the browser. It differs from PCRE, Python and Go in places: JavaScript has no lookbehind in very old engines, no possessive quantifiers, and no inline modifiers. A pattern that works here may need adjusting for a server-side language.
What does the global flag change?
Without it, only the first match is returned. With it, the engine keeps scanning from where the last match ended. It also makes the regex object stateful through its lastIndex property, which is a classic source of bugs when a global regex is reused across calls.
Why does my pattern with .* match too much?
Because quantifiers are greedy by default. They take as much as possible and then backtrack. Adding a question mark makes them lazy, so .*? takes as little as possible. This is the usual fix when a pattern intended to match one tag swallows the whole document.
Is my test data sent anywhere?
No. Both the pattern and the text are evaluated in this tab using the browser's own regex engine. Nothing is transmitted, which matters when you are testing against a sample of production data.
Last reviewed
