Xerobit

Regex Tester

Test regular expressions with live match highlighting. Inspect capture groups, preview replacements, and use preset patterns for common needs. Uses your browser's native JavaScript regex engine, same one you'd use in code.

2 matches
 
Replace preview (optional)
Contact us: [EMAIL: support on xerobit.dev] or [EMAIL: admin on example.com] for help.
Visit https://xerobit.dev/tools.
Server at 192.168.1.1 is down.
Matches with groups
#1 @ 12
$0: support@xerobit.dev
$1: support
$2: xerobit.dev
#2 @ 35
$0: admin@example.com
$1: admin
$2: example.com
Ready. Edit pattern or test string.

How to use the regex tester

  1. Enter your pattern between the slashes at the top. Flags (g, i, m, s, u, y) go in the second input.
  2. Type or paste a test string on the left. Matches highlight live.
  3. Inspect capture groups in the "Matches with groups" list: $0 is the whole match, $1+ are the groups.
  4. Use the Replace input to preview a substitution. Supports $1, $2, and $&.
  5. Dropdown presets give you a starting pattern for email, URL, IPv4, UUID, ISO date, phone, hex color.

JavaScript regex flags: what they do

  • g: global. Find all matches, not just the first. Required for most tools to work usefully.
  • i: case-insensitive.
  • m: multiline. ^ and $ match at line boundaries, not just string boundaries.
  • s: dotall. . matches newlines (off by default).
  • u: Unicode mode. Fixes surrogate-pair handling, enables \\p{...} property classes.
  • y: sticky. Match only at lastIndex; useful in lexers.

Catastrophic backtracking: the regex that kills your server

Patterns like (a+)+b can blow up exponentially on input like aaaaaaaaaaaaaaaaaaaaaaaaaaX. The engine tries every split of the as before giving up. One user-submitted regex on your server is a denial-of-service away.

Defenses:

  • Avoid nested quantifiers on overlapping character classes.
  • Use possessive quantifiers or atomic groups (not in JavaScript: use (?=(X))\\1 idiom).
  • Never run untrusted user regexes on your server without a timeout.

Named capture groups

Use (?<name>...) to name a group. Access in replacement with $<name> and in code via match.groups.name. Much more maintainable than numeric groups once you have more than two.

Common regex patterns reference

NamePatternMatchesTest string
Email[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}Common addressesuser+tag@example.com
URLhttps?://[^\s/$.?#].[^\s]*http/https URLshttps://example.com/path?q=1
IPv4(?:\d{1,3}\.)\{3}\d{1,3}IP addresses192.168.1.100
UUID[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}UUID v4550e8400-e29b-41d4-a716-446655440000
ISO date\d{4}-\d{2}-\d{2}YYYY-MM-DD2026-05-13
Phone (US)(?:\+1\s?)?(?:\(\d{3}\)|\d{3})[\s\-]?\d{3}[\s\-]?\d{4}US phone numbers(555) 867-5309
Hex color#[0-9a-fA-F]{3,6}CSS hex colors#1a2b3c
Slug[a-z0-9]+(?:-[a-z0-9]+)*URL-friendly slugmy-blog-post-title

Lookahead and lookbehind

Lookarounds match a position without consuming characters, they're zero-width assertions. JavaScript supports all four types:

  • Positive lookahead (?=...): match only if followed by the pattern. \d+(?= dollars) matches the number in 100 dollars but not in 100 euros.
  • Negative lookahead (?!...): match only if NOT followed by the pattern. \bfoo(?!bar)\b matches foo alone but not in foobar.
  • Positive lookbehind (?<=...): match only if preceded by the pattern. (?<=\$)\d+ matches the digits in $99 but not in 99 alone. Supported in all modern browsers (ES2018+).
  • Negative lookbehind (?<!...): match only if NOT preceded by the pattern. (?<!\d)\d{4} matches a 4-digit number not preceded by another digit.

A common use: extract values without the surrounding delimiter, (?<="title":")[^"]+ pulls the title string value from a JSON fragment.

Quantifiers quick reference

QuantifierMeaningExample
*0 or more (greedy)a* matches "", "a", "aaa"
+1 or more (greedy)a+ requires at least one "a"
?0 or 1 (optional)colou?r matches "color" and "colour"
{n}Exactly n times\d{4} matches exactly 4 digits
{n,}n or more times\w{3,} matches 3+ word chars
{n,m}Between n and m times\d{2,4} matches 2 to 4 digits
*? / +?Lazy (minimal match)<.+?> matches one tag, not all tags

Greedy quantifiers expand as far as possible and then backtrack. Lazy quantifiers (? suffix) shrink to the minimum possible match. When parsing HTML-like structures, lazy is almost always what you want.

Regex performance tips

  • Anchor with ^ and $: if you only want to match the full string, anchoring eliminates most backtracking. ^\d+$ is far faster than \d+ on a long string.
  • Avoid .* in the middle of patterns: foo.*bar forces the engine to scan to the end of the string and backtrack. If you know the separator, be specific: foo[^b]*bar.
  • Use character classes instead of alternation: [aeiou] is faster than a|e|i|o|u. Alternation causes the engine to try each branch sequentially.
  • JavaScript has no possessive quantifiers: in PCRE you'd use a++ to prevent backtracking into the quantifier. In JS, simulate with a lookahead workaround: (?=(a+))\1 captures greedily without allowing the engine to give back characters.
  • Pre-compile regexes outside loops: in Node.js, /pattern/flags literals are compiled once. Avoid new RegExp(str) inside a loop unless the pattern changes, each constructor call re-compiles the regex.

FAQ

Does this match PCRE or JavaScript flavor?

JavaScript. This tool uses your browser's native RegExp engine, so results match exactly what your Node.js, Deno, or browser code will produce. PCRE has features JS lacks: atomic groups, possessive quantifiers, some advanced lookbehind forms, and the \K reset. If your regex uses those and you're targeting Node.js, you'll need a PCRE-compatible library like re2 or reconsider your approach.

Can I test with large inputs?

Yes, but the highlighted matches are capped at 200 visible entries to keep the UI responsive. Matching itself handles up to 10,000 match iterations before safety-cutting. For testing against very large files (multi-MB logs), the browser handles input up to several MB but UI highlighting may lag, reduce the test string to a representative sample.

Is anything sent to a server?

No. Everything runs in your browser. Your regex patterns and test strings never leave your machine.

Why does my valid regex fail when I paste it into code?

Two common causes: first, missing flags: this tool defaults to g (global), but if you paste the pattern into code without adding the same flags, behavior differs. Second, escaping differences: in a JavaScript regex literal (/pattern/) a backslash is literal: /\d/. In a string passed to new RegExp(str), backslashes must be doubled: new RegExp("\\d"). A pattern that works in this tester (which uses regex literals) may fail in new RegExp() if you forget to double the backslashes.

Pillar