Regex Tester

Test a regular expression against real text, see every match highlighted with its capture groups, and read back what the pattern says.

Processed on your device — no upload

termiva regex '[\w.]+@[\w.]+' --flags g

Global is always on, so every match is found rather than only the first. The others are yours: i ignores case, m makes ^ and $ match each line, s lets . cross newlines.

2 matches

Contact ali@example.com or sara@company.org
Invoice INV-2025-0431 dated 2025-01-14
Phone +962 7 9012 3456
Total: 1,240.50 JOD
  • at 8ali@example.com
  • at 27sara@company.org

What the pattern says, token by token:

  • any one of \w. — [\w.]
  • one or more of the last thing — +
  • any one of \w. — [\w.]
  • one or more of the last thing — +
matches 2flags gnothing uploaded

How to use it

  1. Type or paste your pattern.
  2. Paste the text you expect it to match, and turn on any flags you need.
  3. Read the highlighted matches and their capture groups.

How it works

The pattern runs through your browser's own regular expression engine — the same one that will run it when you paste it into JavaScript. That matters more than it sounds: every language's flavour differs in the details, and a pattern verified against PCRE or Python can behave differently in a browser. What you see here is whatString.replace and RegExp.exec will do.

Matches are highlighted in place rather than only listed, because the interesting failures are positional. A pattern that matches too much, matches across a line break you did not expect, or matches an empty string at every position looks fine in a list of results and obvious when you can see where it landed.

Two guards run underneath, and they exist for a specific reason. A regular expression is arbitrary code, and some innocent-looking ones take longer than the age of the universe on a forty-character string — the classic being nested quantifiers like (a+)+b, which backtracks catastrophically. In a browser that is not an error, it is a frozen tab. So matching stops after five hundred results or one second, whichever comes first, and says that it stopped.

The second guard is smaller and catches something almost everyone writing this kind of loop forgets. A pattern that can match the empty string — a* against bbb — matches at every position without advancing, so a naive loop sits on character zero for ever. The position is nudged forward when a match is empty.

The plain-language reading below the results is deliberately shallow. It explains the tokens people most often copy without understanding and stays silent about the rest, because a confident wrong explanation of a regular expression is worse than none — the entire difficulty with them is that people believe what they think they say.

A worked example

You need to pull every email address out of a support export. You start with \w+@\w+ and it finds ali@example — the dot in .com is not a word character, so the match stops there. The highlight makes that visible immediately; a list of results would just look short.

Change it to [\w.]+@[\w.]+ and the full addresses light up. Now add a capture group — ([\w.]+)@([\w.]+) — and each result lists $1 and $2, the user and the domain, which is what you would reference in a replacement.

Then try the replacement box. Put $2 in it and the whole text comes back with every address reduced to its domain. That is exactly what text.replace(/([\w.]+)@([\w.]+)/g, '$2') will do in your code, because it is what just ran.

One more worth trying. Turn on m and put ^ at the front of a pattern: it starts matching at every line rather than only at the start of the whole text. That single flag is behind a large share of patterns that work in a tester and fail on real multi-line input.

Questions

Which regex flavour is this?

JavaScript, because it is your browser’s own engine running it. If you are writing Python, PHP or Go, most of what you test here will carry across — but lookbehind, named group syntax and some Unicode property escapes differ, so verify anything unusual in the language you are targeting.

Why is the global flag always on?

Without it the engine returns the first match and stops, which makes a tester useless — you would never see whether the pattern matches the second occurrence correctly. Everything else is yours to turn on and off.

What do i, m, s and u actually do?

i ignores case. m makes ^ and $ match at every line rather than only at the ends of the whole text. s lets the dot match newlines, which it otherwise does not. u turns on full Unicode handling, which you need for emoji and for \p{...} property escapes.

Why did it stop before finding everything?

It stops after 500 matches or one second. Both limits exist so a pattern that matches everywhere, or one that backtracks badly, cannot lock up the tab. When it stops early it says so rather than presenting a partial list as complete.

My pattern works here but not in my code. Why?

The usual causes are escaping and flags. A pattern typed into a field is a raw string; the same pattern in source code goes through the language’s string escaping first, so \d often needs to be written \\d. And a flag you toggled here has to be present there too.

Is my text sent anywhere?

No. The pattern and the text are handed to your browser’s regex engine and nothing else. The site is static files with no backend, so there is no endpoint to send them to — which is worth knowing, because the text people test patterns against is usually production data.

Is Regex Tester free to use online?

Yes — free, with no account, no daily limit and no watermark. It runs online in your browser, and because the work happens on your own device it keeps working offline once the page has loaded.

Reading