bitlvl
EN

Regex tester

Type a pattern and flags, paste the text to search. Matches light up as you type, each group is listed, and the pattern is explained piece by piece.

//

Matches

Replace

 

Explanation

Cheat sheet

TokenMatches
.Any character except newline (with the s flag: any character)
\d \w \sDigit; word character [A-Za-z0-9_]; whitespace. Upper case negates: \D \W \S
[abc] [^abc] [a-z]Character class, negated class, range
^ $Start and end of input (of each line with the m flag)
\bWord boundary
* + ? {n} {n,} {n,m}0 or more, 1 or more, 0 or 1, exactly n, n or more, n to m
*? +? ??Lazy (shortest) versions
(abc)Capture group, numbered from 1
(?<name>abc)Named group, referenced as \k<name> and $<name>
(?:abc)Group without capture
a|bAlternation
(?=x) (?!x) (?<=x) (?<!x)Lookahead, negative lookahead, lookbehind, negative lookbehind
\1Backreference to group 1
\p{L} \p{Script=Cyrillic}Unicode property (needs the u flag)

Flags

g find all matches, not just the first; i ignore case; m make ^ and $ match at line breaks; s let . match newlines; u Unicode mode (needed for \p{…} and for correct handling of emoji); y sticky, match only at lastIndex.

Flavours

This tester uses the JavaScript engine. The syntax above is shared with PCRE (PHP, nginx, HAProxy), Python's re and Java for nearly everything you will write; the differences are at the edges: Python names groups (?P<name>…), Go's RE2 and grep -E have no lookbehind or backreferences, and POSIX classes like [[:digit:]] are not JavaScript. Atomic groups and possessive quantifiers exist in PCRE and Java only.

Common patterns

IPv4 address (loose)
\b(?:\d{1,3}\.){3}\d{1,3}\b
Email (practical)
[\w.+-]+@[\w-]+(?:\.[\w-]+)+
ISO date
(?<y>\d{4})-(?<m>0[1-9]|1[0-2])-(?<d>0[1-9]|[12]\d|3[01])
Hex colour
#(?:[0-9a-f]{3}){1,2}\b
Trim trailing whitespace
[ \t]+$ (flags gm, replace with nothing)

Questions

Why does my pattern match only once?

Without the g flag a regex finds the first match only. Add g to find all. In code, use matchAll, re.findall or preg_match_all for the same effect.

Why is .* matching too much?

Quantifiers are greedy: .* takes as much as possible and backs off only if the rest fails. Use .*? for the shortest match, or a negated class like [^"]* which is both faster and clearer.

How do I match a literal dot or bracket?

Escape it with a backslash: \. \[ \( \\. The string-escape tool has a regex mode that escapes a whole literal for you.

What is catastrophic backtracking?

Nested quantifiers like (a+)+ on a non-matching input make the engine try exponentially many paths and hang. Avoid nesting quantifiers over overlapping sets, use possessive or atomic groups where the engine has them, or use RE2 (Go, Rust regex), which guarantees linear time.