Online Regex Tester
Test any regular expression against real text with live highlighting, capture groups, a replacement preview and switchable flags.
Writing a pattern for phone numbers or a log timestamp from memory rarely works the first time: boundaries, greedy matching and one escaping level too many only become visible against real input. JavaScript also has its own dialect, so a pattern that works in one language may need rewriting before it runs here.
Matching uses the browser's native RegExp engine and runs as you type, inside a Web Worker that is terminated if it exceeds its time budget. Your pattern and test text are not sent anywhere, which matters when the text is a production log. Besides highlighting, the page lists the position and capture groups of every match, and the replacement preview shows what a substitution would produce before you apply it in code.
Greedy and lazy quantifiers
Quantifiers are greedy by default: .* consumes as much as it can and only backtracks when the rest of the pattern cannot match. Adding ? makes it lazy, so .*? stops at the first position where the remainder of the pattern succeeds. Against the string <a><b>, the pattern <.*> matches the whole thing while <.*?> matches only <a>. Laziness is not automatically better: a negated class such as [^>]* reaches the same result with fewer steps and is easier to reason about, which also makes catastrophic backtracking less likely.
Catastrophic backtracking and why pages freeze
A pattern like (a+)+b against input that fails to match makes the engine try exponentially many ways to split the string: a couple of dozen characters is enough to push JavaScript into hundreds of thousands of backtracking steps while the tab stops responding. This is ReDoS, and it comes from the pattern, not from the tool. The defenses are the same everywhere: avoid nested quantifiers, replace .* with a precise character class, bound the input length, and if the pattern is driven by user input, run it where a timeout and a resource limit can be enforced. This page runs matching in a Web Worker and kills it after a fixed time budget, so a pathological pattern costs you that one run instead of the page.
Flags, Unicode and dialect differences
The g flag finds every match instead of only the first, i ignores case, m makes ^ and $ match at each line boundary rather than at the start and end of the whole text, s lets the dot match line breaks, and u switches on Unicode mode. The u flag is what makes property escapes work - \p{Letter} for any letter, \p{Script=Han} for Han characters - and it is the only way to handle characters outside the Basic Multilingual Plane correctly, emoji included. The pattern library here ships the everyday ones: E.164 phone numbers, email, URL, IPv4, IPv6, UUID, US ZIP codes, ISO 8601 dates, HTML tags and JSON string values. Keep in mind that JavaScript does not support every PCRE construct - \K, recursion and possessive quantifiers have no equivalent, and a pattern copied from another language often has to be rewritten.
Frequently asked questions
- Why does my regex freeze the browser?
- Almost always catastrophic backtracking. Nested quantifiers such as (a+)+ or (.*)* make a failing match try an exponential number of combinations, and shortening the test text only hides the problem. Rewrite the pattern with negated classes and bounded quantifiers. A run that exceeds the time budget here is terminated rather than allowed to hang the tab.
- What does the g flag do?
- Without it only the first match is returned and only the first occurrence is replaced; with it you get every match. One trap: when you reuse the same regex object with test or exec, lastIndex accumulates between calls and results become intermittent. Reset it, or build the regex once per run - matching and replacing here always create a fresh one.
- How do I match non-Latin text or Unicode categories?
- Use the u flag with a property escape: \p{Script=Han} matches Han characters, \p{Letter} any letter, \p{Script=Cyrillic} a whole script, and \p{Emoji} emoji. Property escapes only work in Unicode mode, and they cover far more than a hand-written code point range, including characters in the extension blocks.
- What are $1 and $2 in a replacement?
- References to the first and second capture groups. They only exist if the pattern contains the corresponding parentheses, numbering follows the order of the opening brackets, and non-capturing groups written (?:...) are not counted. Writing $2-$1 swaps the two groups, a dollar sign and an ampersand together stand for the whole match, and a named group is written as a dollar sign followed by the name in angle brackets.