Regex Tester
Test and debug regular expressions in real time.
Click a token to insert it into the pattern.
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.