Regex Tester

Test a regular expression, see every match and get the pattern explained

Runs entirely in your browser. Your data never leaves this device.

Pattern, then <<<, then test text
Matches

    

How to use it

  1. Put the pattern on the first line. /pattern/flags is accepted, or just the bare pattern.
  2. Add a line containing only <<<, then the text to test against.
  3. Read the match list, the highlighted text, and the pattern breakdown.

What the three panes tell you

The match list is the ground truth: each match with its offset, plus every numbered and named capture group. This is where you catch the classic off-by-one — a group that captured an empty string instead of nothing, or matched one character more than intended.

The highlighted view shows the matches in context. It answers a different question: not "what did it capture" but "did it find them all". A pattern that works on your example and silently skips the third line is obvious here and invisible in a match count.

The explanation decomposes the pattern token by token. It is most useful on someone else's regex — the ones that arrive in a code review with no comment.

Two mistakes that account for most confusion

Escaping. A regex written inside a string literal is escaped twice. In C# "\\d+" is the pattern \d+; in a verbatim string @"\d+" it is the same thing written once. When a pattern that works in a tester fails in code — or the reverse — count the backslashes first.

Greediness. Quantifiers are greedy by default: they consume as much as they can, then give characters back only as needed to let the rest of the pattern match. ".*" against "a" and "b" matches the entire string including the middle, because the final " can be satisfied by the last quote. Add ? to make it lazy — ".*?" — and you get the two intended matches. Most "my regex grabbed too much" bugs are this.

Catastrophic backtracking is a security issue

Some patterns take exponential time on inputs that nearly match. The textbook case is (a+)+$ fed a long string of a followed by b: the engine tries every way of splitting the as before concluding there is no match.

This matters because regular expressions frequently validate user input. A pattern with nested quantifiers over overlapping alternatives — email validators are a common offender — becomes a denial-of-service vector: one crafted request pins a CPU core. It has a name, ReDoS, and it appears in real incident reports.

Three defences. Avoid nesting quantifiers over patterns that can match the same text in multiple ways. Test with near-miss inputs, not just matching ones, since the pathological case is always a failure to match. And in .NET, pass a matchTimeout to Regex — a hard ceiling costs nothing and turns a hang into an exception you can handle.

Where JavaScript and .NET differ

The syntax overlaps heavily, so a pattern tested here will usually behave the same in C#. The gaps worth knowing:

  • Balancing groups — .NET's (?<open>) / (?<-open>) can match nested structures. JavaScript has nothing comparable.
  • Lookbehind — long a .NET feature, now standard in JavaScript too, but check your target runtime.
  • RegexOptions.IgnoreCase and culture — .NET case-insensitivity is culture-sensitive by default, which produces the Turkish i problem: under a Turkish culture, I and i are not a case-insensitive match. Use CultureInvariant unless you specifically want locale rules.
  • Named group access — .NET exposes match.Groups["name"]; JavaScript uses match.groups.name.

Frequently asked questions

Which regex flavour is this?

JavaScript, because it runs in your browser. Most patterns are portable, but .NET, PCRE and Python each add features JavaScript lacks — .NET balancing groups and recursive patterns have no equivalent here.

Why does my pattern match nothing?

Two common causes. Backslashes: if you copied the pattern out of a string literal, `\\d` in the source is `\d` in the actual pattern. And anchors: `^` and `$` match the whole string unless you enable the m flag.

What is the difference between greedy and lazy?

`.*` takes as much as possible then backs off; `.*?` takes as little as possible then grows. Matching `<a>text</a>` with `<.*>` captures the whole string, while `<.*?>` captures just `<a>`.

How do named groups work?

`(?<name>...)` captures into a named slot instead of a number, so you read `match.groups.name` rather than counting brackets. Both JavaScript and .NET support the syntax, and it makes patterns far easier to maintain.

What is catastrophic backtracking?

A pattern with nested quantifiers over overlapping alternatives, like `(a+)+b`, can take exponential time on a non-matching input. If a regex runs on user input, this is a denial-of-service vector — test with strings that nearly match but do not.

Should I parse HTML with regex?

No. HTML nesting is not a regular language, so no regular expression can handle it correctly in general. Use a parser — `DOMParser` in the browser, AngleSharp or HtmlAgilityPack in .NET.

Related tools

browse category →

Last updated: