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

  1. Enter your regular expression in the pattern field.
  2. Enter or paste sample text to test against.
  3. 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.