Regex Tester

Test and debug regular expressions in real time.

Pattern
/ /g
Test String

Regular expressions (regex) are patterns used to find, match, and extract text. This tester uses the browser's built-in JavaScript regex engine — the same one used in String.prototype.match(), replace(), and matchAll().

Flags change how matching works: g finds all matches (without it, only the first is returned); i ignores case; m makes ^ and $ match line boundaries instead of the whole string; s (dotAll) makes . match newlines; u enables full Unicode support.

Capture groups let you extract parts of a match. Use () for numbered groups and (?<name>) for named groups. Non-capturing groups (?:) group without capturing, which is faster when you don't need the captured value.

Greedy vs. lazy: quantifiers like * and + are greedy by default — they match as much as possible. Adding ? makes them lazy: .*? matches as little as possible.

Catastrophic backtracking is what happens when one quantifier is nested inside another, as in (a+)+. On text that does not match, the engine tries every way of dividing the characters between the inner and outer quantifier, and the number of ways roughly doubles with each character added — so the test string does not need to be long. Thirty characters is already enough to run for hours. This tester matches in a background Web Worker and stops any pattern still running after 2 seconds, so a pattern like that costs you a warning rather than the tab.

What do the regex flags mean?

g = global (find all matches, not just the first). i = case-insensitive. m = multiline (^ and $ match line boundaries). s = dotAll (. matches newlines). u = Unicode (enables full Unicode support and stricter parsing). d = generate match indices (start/end positions).

What is the difference between .* and .*?

.* is greedy — it matches as many characters as possible. .*? is lazy — it matches as few characters as possible. Example: on "aXbXc", a.*X matches "aXbX" (greedy), while a.*?X matches "aX" (lazy).

How do I match a literal dot or parenthesis?

Escape it with a backslash: \. matches a literal dot, \( matches a literal opening parenthesis. Without escaping, . matches any character and ( starts a capture group.

What is a capture group?

Parentheses () create a capture group that extracts the matched substring. Example: (\d{4})-(\d{2})-(\d{2}) on "2024-01-15" captures group 1 = "2024", group 2 = "01", group 3 = "15". Named groups use (?<name>...) syntax.

What causes catastrophic backtracking?

A quantifier nested inside another one, like (a+)+, on text that does not match. The engine tries every way of dividing the characters between the two quantifiers before it can conclude the match failed, and the number of ways roughly doubles per character — so it is the nesting that causes it, not the length of the test string. (a+)+$ against 30 letters will run for hours. Avoid overlapping quantifiers on the same characters. This tester runs matching in a Web Worker and cancels any pattern still going after two seconds, so it warns you instead of freezing the tab.

This site is vibe coded. The tools here were built largely by AI, so treat what they tell you as a starting point rather than an answer — double-check anything that matters before you rely on it.

Crunchify.net — 98 free tools, no ads, no tracking.