Live Matching · Groups · Common Patterns

Regex Tester

Test regular expressions in real time. See all matches highlighted, inspect capture groups, toggle flags, and load common patterns for emails, URLs, dates, and more.

Last updated

Live Highlighting
Capture Groups
Flags: g, i, m, s
Common Patterns
Our networkfavorit5The 5 worth buying.Top fives, comparisons and what reviewers say.See the top 5s
⚡
Regex Tester
JavaScript RegExp · Live matching · Flags g i m s u y
Regular Expression
/ /
Common Patterns
Test String
Match Highlights

Regular Expressions Quick Reference

A regular expression matches text by pattern: \d{3}-\d{4} finds 555-1234, and the g flag finds every match instead of only the first. Type a pattern and some test text above to see matches highlighted live, with capture groups and positions. The tester uses your browser's JavaScript RegExp engine, runs locally, and stops runaway patterns after 1.5 seconds.

Regular expressions (regex) are patterns for matching text. The syntax below applies to JavaScript RegExp (used by this tester) and is largely compatible with Python, Java, and most modern languages.

Character Classes

\d = digit [0-9]. \w = word [a-zA-Z0-9_]. \s = whitespace. \D, \W, \S = negated. [abc] = a, b, or c. [^abc] = not a, b, or c. [a-z] = lowercase letter. . = any char except newline.

Quantifiers

* = 0 or more. + = 1 or more. ? = 0 or 1. {n} = exactly n. {n,} = n or more. {n,m} = between n and m. Add ? after to make lazy (minimal): *? +? ?? {n,m}?

Anchors & Boundaries

^ = start of string (or line with m flag). $ = end of string (or line with m flag). \b = word boundary. \B = non-word boundary. Use ^ and $ together to match the entire string.

Groups & Lookaround

(abc) = capture group. (?:abc) = non-capturing group. (?<name>abc) = named group. | = alternation (or). (?=abc) = lookahead. (?!abc) = negative lookahead. (?<=abc) = lookbehind.

JavaScript Regex Flags Explained

FlagNameEffectExample
gglobalFind all matches, not just the first/a/g on "banana": 3 matches
iignoreCaseLetters match either case/cat/i matches "CAT"
mmultiline^ and $ match at every line start and end/^\d+/gm finds a number at the start of each line
sdotAll. also matches line breaks/a.b/s matches "a\nb"
uunicodeWorks in code points; enables \u{...} and \p{...}/^.$/u matches one emoji; without u it does not
ystickyEach match must start exactly where the last one ended/\d/gy on "12a3": 2 matches (1, 2)

Without g the tester shows only the first match, exactly like str.match(/x/) or re.exec(str). The y flag is used by tokenizers that must not skip characters; in the example, "3" is not matched because "a" breaks the chain.

Regex Token Cheat Sheet

TokenMatchesExample
\d \w \sDigit, word character [A-Za-z0-9_], whitespace\w+ on "id_42!" gives "id_42"
[abc] [^abc] [a-z]One of, none of, a range[aeiou] finds vowels
* + ? {n,m}0 or more, 1 or more, optional, n to m timescolou?r matches color and colour
*? +?Lazy versions: as few as possible<.+?> matches one tag
^ $ \bStart, end, word boundary\bcat\b skips "concat"
( ) (?: ) (?<name> )Capture, group only, named capture(?<year>\d{4})
a|bEither sidecat|dog
(?= ) (?! ) (?<= ) (?<! )Lookahead and lookbehind, positive and negative\d+(?=%) takes 15 from "15%"
\1 \k<name>Backreference to a group(\w)\1 finds "ll" in "hello"
\p{L} (needs u)Any Unicode letter\p{L}+ matches "Zoë"

Catastrophic Backtracking and Zero-Length Matches

JavaScript's regex engine backtracks: when a match fails, it tries every other way the pattern could have split the text. With nested quantifiers such as (a+)+$, (\w+\s?)*$ or overlapping alternatives like (a|aa)*$, the number of ways roughly doubles with each extra character. In a Node.js test, (a+)+$ against 24 a's followed by "!" took about a quarter of a second, and every two more a's made it about four times slower, so 30 a's already take many seconds. That is why the tester runs matching in a background worker and stops it after 1.5 seconds.

  • Remove the nesting: (a+)+ matches the same strings as a+.
  • Make the parts exclusive: (\w+\s)*\w+ instead of (\w+\s?)*, so each character can be matched only one way.
  • Anchor and limit: use ^, $ and bounded counts like {1,64} when validating input on a server, where a slow pattern can be a denial of service risk.

Patterns that can match an empty string, such as a*, \b or (?=x), produce zero-length matches. With the g flag the engine then moves ahead one character (one code point with u) and tries again, so a* on "baa" gives 3 matches: "" at 0, "aa" at 1 and "" at 3. The tester counts these separately in the stats bar.

Common Patterns Ready to Copy

PurposePatternNotes
US ZIP code^\d{5}(-\d{4})?$12345 or 12345-6789
US phone^\(?\d{3}\)?[ .-]?\d{3}[ .-]?\d{4}$Format check only, not a real number check
ISO date^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$Still accepts 2026-02-31; check the date in code
Hex color^#([0-9a-f]{3}|[0-9a-f]{6})$ with i#fff or #00a67e
Whole word\bword\bWord boundaries use ASCII \w, even with u
Trim spaces^\s+|\s+$ with gReplace with an empty string

Regex is a poor fit for nested formats. To check JSON, use the JSON formatter; to compare two texts, the diff checker.

Method and sources. Matching uses the JavaScript RegExp engine built into your browser, as specified in ECMAScript 2025 (ECMA-262), including the RegExpBuiltinExec rules for the global, sticky and unicode flags and the AdvanceStringIndex rule for empty matches. Flag and token examples were checked by running them in Node.js. Backtracking behaviour as described in the OWASP guidance on Regular expression Denial of Service (ReDoS).

Frequently Asked Questions

A regular expression is a sequence of characters that defines a search pattern. Regex is used to find, validate, and manipulate text. A pattern like \d{3}-\d{4} matches phone number segments (three digits, dash, four digits). Regex is supported in virtually every programming language and text editor. The syntax has a common core (derived from Perl) with some language-specific variations. This tester uses JavaScript's RegExp engine.

g (global): Find all matches, not just the first. Without g, only the first match is returned. i (case-insensitive): Match [a-z] and [A-Z] interchangeably. m (multiline): ^ and $ match start/end of each line, not just start/end of the entire string. s (dotAll): The dot (.) matches newlines too. By default, dot doesn't match \n. Enable dotAll when matching across multiple lines with dot.

A basic email regex: [a-z0-9._%+\-]+@[a-z0-9.\-]+\.[a-z]{2,} (use i flag for case-insensitive). This matches: local part (letters, digits, dots, underscores, percent, plus, minus) + @ + domain + . + TLD (2+ letters). No regex perfectly validates all valid email addresses per RFC 5321/5322, which allows many edge cases. For real validation, combine basic regex with sending a confirmation email. The HTML5 email input type has a reasonable built-in validation pattern.

A capture group (pattern) saves the matched text for later use. Example: (\d{4})-(\d{2})-(\d{2}) matches dates like 2026-05-13 and captures year, month, day as groups 1, 2, 3. In JavaScript: match[1]='2026', match[2]='05', match[3]='13'. Named groups (?<year>\d{4}) let you access captures by name: match.groups.year. Non-capturing groups (?:pattern) group without saving, useful with alternation: (?:cat|dog)s matches both "cats" and "dogs".

In regex, many characters have special meanings: . * + ? ^ $ { } [ ] | ( ) \. To match them literally, escape with a backslash: \. matches a literal dot, \* matches a literal asterisk. Example: to match "3.14", use 3\.14. Without escaping, 3.14 would match "3X14", "3_14", etc. (since . matches any character). Common escapes: \. \* \+ \? \( \) \[ \] \{ \} \\ \^

Greedy quantifiers (*, +, {n,m}) match as much as possible. Lazy quantifiers (*?, +?, {n,m}?) match as little as possible. Example with HTML: <.+> on "<b>text</b>" greedy matches the entire "<b>text</b>". <.+?> lazy matches just "<b>". Use lazy matching when you want the smallest possible match: common in HTML parsing, where greedy would consume from the first opening tag to the last closing tag.

Two ways to create: Literal: const re = /pattern/flags. Constructor: const re = new RegExp('pattern', 'flags'). Key methods: re.test(str) → returns true/false. str.match(re) → array of matches (or null). str.matchAll(re) → iterator of all match objects (requires g flag). str.replace(re, replacement) → returns new string. str.split(re) → splits into array. Use matchAll for complex patterns with capture groups across all matches.

A reasonable URL regex: https?:\/\/[^\s/$.?#].[^\s]* matches http:// or https://, followed by a non-whitespace domain, followed by any non-whitespace path. More precise: https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&=]*). Complete URL validation is notoriously difficult with regex: use the URL constructor in JavaScript (new URL(str)) which throws on invalid URLs.

Lookaround assertions match a position, not characters: they don't consume text. Positive lookahead (?=x): match if followed by x. \d+(?= dollars) matches numbers followed by " dollars". Negative lookahead (?!x): match if NOT followed by x. \d+(?! dollars) matches numbers not followed by " dollars". Positive lookbehind (?<=x): match if preceded by x. (?<=\$)\d+ matches numbers after a dollar sign. Negative lookbehind (?<!x): match if NOT preceded by x. Lookbehind is not supported in Safari before version 16.4.

Two different scenarios: (1) Match ^ and $ at each line boundary, enable the m (multiline) flag. Now ^ matches start of each line and $ matches end of each line, not just the whole string. (2) Match content that spans multiple lines, enable the s (dotAll) flag so that . matches \n too. Without s flag, [\s\S]* is a common workaround that matches any character including newlines. Combine both flags when you need both behaviors: multiline anchors AND cross-line matching.

It makes each match start exactly at lastIndex, with no searching ahead. /\d/gy on "12a3" finds 1 and 2, then stops at "a", while /\d/g also finds 3. Sticky matching is used in lexers and parsers that consume input piece by piece.

Most likely catastrophic backtracking: a quantifier inside another quantifier, such as (a+)+ or (\w+\s?)*, lets the engine split the text in exponentially many ways when the overall match fails. This tester stops the search after 1.5 seconds. Rewrite the pattern so each character can be matched only one way, for example a+ instead of (a+)+.