About Regex Tester
Regular expressions are the sharpest text-processing tool in programming and the easiest to cut yourself on: a pattern that looks right can silently match too much, too little, or — worse — hang your service. A regex tester closes the feedback loop: you see live, highlighted matches against real sample text as you type, so mistakes surface in seconds instead of in production.
This tester uses the JavaScript (ECMAScript) regex engine — the same one running in Node and every browser — with g, i, and m flags, match highlighting, and a built-in cheat sheet. Large inputs are processed in a Web Worker so a heavy pattern cannot freeze the page. Your text never leaves the browser.
How to use Regex Tester
- Enter your regular expression in the pattern field.
- Enter or paste sample text to test against.
- View matches and groups in real time.
Example
Input
Your input or data here
Output
Result will appear here after running the tool
A 90-second refresher on the pieces that matter
Character classes: \d digit, \w word character (letters, digits, _), \s whitespace; capitals negate (\D = non-digit). [abc] matches one of a/b/c; [^abc] anything else. Quantifiers: * (0+), + (1+), ? (0 or 1), {2,5} (two to five) — all greedy by default, taking as much as possible; append ? to make them lazy. Anchors: ^ start, $ end (per-line with the m flag), \b word boundary. Groups: (…) captures, (?:…) groups without capturing, (?<name>…) captures by name.
The three bugs that account for most broken regexes
Greedy overmatch: <.+> against '<a><b>' matches the whole string, because + grabs maximally. Fix with lazy (<.+?>) or, better, a negated class (<[^>]+>) which is also faster.
Unescaped metacharacters: . matches any character, so 1.5 matches '125'. Escape literals: 1\.5, especially in dots of domain names and IP addresses — a validation regex with unescaped dots accepts far more than intended.
Anchor amnesia: ^\d{4}$ validates a whole string as four digits; without anchors, \d{4} merely finds four digits anywhere — 'abc12345' passes. Validation regexes almost always need both anchors.
Catastrophic backtracking — the regex that takes down services
Patterns with nested or overlapping quantifiers — (a+)+$, (\w+\s?)*$ — can force the engine to try exponentially many ways to split the input before concluding there is no match. On a crafted 30-character string, that is minutes of CPU: this is ReDoS (regex denial of service), and it took Cloudflare down globally in 2019 via one pattern in a WAF rule.
Defenses: avoid nested quantifiers over overlapping character sets; prefer negated classes ([^"]* instead of .*? inside quotes); test patterns against long non-matching inputs (this tester's worker keeps the page alive while you do); and in Node 20+/modern runtimes consider the non-backtracking RE2 library for untrusted input.
JavaScript flavor specifics
- Flags: g (all matches), i (case-insensitive), m (^ $ per line), s (dot matches newline), u (proper Unicode), y (sticky).
- Lookbehind (?<=…) is supported in all modern engines (Node 8.3+, all evergreen browsers).
- \d is ASCII-only: Thai ๑ or Arabic ٣ digits need \p{Nd} with the u flag.
- No possessive quantifiers or atomic groups (unlike Java/PCRE); emulate with careful pattern design.
- In string.replace, $1 refers to group 1; $$ is a literal dollar sign.
Common errors and how to fix them
Pattern matches way more than intended
Cause: Greedy quantifier spanning across delimiters (.+ or .* crossing the boundary you meant to stop at).
Fix: Use a negated character class up to the delimiter ([^>]+, [^"]*) or a lazy quantifier — and verify against text containing multiple delimiters.
Validation accepts invalid input
Cause: Missing ^…$ anchors — the regex finds a valid substring inside invalid input.
Fix: Anchor both ends for validation. With the m flag, remember ^ $ become per-line anchors; use \A \z equivalents by removing m.
'Nothing to repeat' / 'Invalid regular expression' error
Cause: A quantifier with nothing before it (*abc), an unescaped special character (+ ? ( ) [ at the wrong spot), or an unclosed group/class.
Fix: Escape literal specials with a backslash; count parentheses and brackets. The error position in the message points at the offending token.
Works here, fails in my code
Cause: Double escaping: in a string literal, \d must be written "\\d" — or the target uses another flavor (grep BRE, Java, RE2) with different syntax.
Fix: In JS, prefer regex literals (/\d+/) over new RegExp strings. When porting, check flavor differences: lookbehind, \p{…}, backreference syntax.
Only the first occurrence is found/replaced
Cause: Missing g flag — exec/replace stop after the first match.
Fix: Enable g here to preview all matches; use /pattern/g (or replaceAll) in code.
Tips and best practices
- Test against three inputs: a clean match, a near-miss that must fail, and a pathological long string — the third catches both overmatching and ReDoS.
- Prefer [^x]* over .*? when scanning to a delimiter x: same semantics, no backtracking pressure.
- Name your groups ((?<year>\d{4})) — self-documenting patterns survive code review and refactoring far better.
- Regex is the wrong tool for nested structures (HTML, JSON, parentheses) — use a parser; the famous Stack Overflow answer about parsing HTML with regex exists for a reason.
- Build incrementally: get the literal skeleton matching first, then generalize one piece at a time, watching the highlight update.
Frequently asked questions
- Which regex flavor does this tester use?
- JavaScript (ECMAScript), identical to Node and browsers. Most patterns port to PCRE/Python with minor changes, but flavors diverge on lookbehind, Unicode classes, and possessive quantifiers — test in the target environment before shipping.
- What do the g, i, m flags do?
- g finds all matches instead of stopping at the first; i ignores case; m makes ^ and $ match at every line boundary rather than only the string's ends. They combine freely (gim).
- Why does my pattern freeze on long input?
- Catastrophic backtracking: nested/overlapping quantifiers like (a+)+ explore exponential split combinations on non-matching input. Rewrite with negated classes or atomic structure. This page runs big inputs in a Web Worker, so the tab survives while you debug.
- Greedy vs lazy — which should I use?
- Greedy (default) grabs the longest match, lazy (?) the shortest. For 'up to the next delimiter', the negated character class beats both: [^,]+ is precise and backtracking-free. Reserve lazy quantifiers for when a negated class can't express the boundary.
- How do I match across multiple lines?
- Two different needs: m changes anchors (^ $ per line); s makes . match newlines. To capture a block spanning lines, you typically want s (or [\s\S] as the classic workaround), not m.
- Is my sample text uploaded?
- No — matching runs entirely in your browser (in a background worker for large inputs).
Embed this tool
Add Regex Tester to your own site, blog post, or internal docs — free, no signup. The widget runs entirely in your visitors' browsers, same as it does here.