Learning & reference

Regex cheat sheet

Every token you actually use, the flags that change everything, ready-made patterns you can paste straight in — and the traps that turn a working regex into a production incident.

Character classes

TokenMatchesExample
.Any character except newline (unless the s flag is set)a.c matches abc, a c
\dA digit, 0-9\d{4} matches 2026
\DAnything that is not a digit
\wWord character: letter, digit or underscore\w+ matches user_1
\WAnything that is not a word character
\sWhitespace: space, tab, newline\s+ collapses runs of spaces
\SAnything that is not whitespace
[abc]Any one of a, b or c[aeiou] matches a vowel
[^abc]Any character except a, b or c
[a-z]A range[A-Za-z0-9] is alphanumeric

Anchors & boundaries

TokenMatchesExample
^Start of the string (or of a line with the m flag)^Error
$End of the string (or of a line with m)\.log$
\bA word boundary\bcat\b matches cat but not concatenate
\BNot a word boundary

Quantifiers

TokenMatchesExample
*Zero or moreab* matches a, abbb
+One or more\d+
?Zero or one (optional)colou?r
{3}Exactly three\d{3}
{2,}Two or more
{2,5}Between two and five
+? *? {n,m}?Lazy - match as few as possible<.+?> stops at the first >

Greedy vs lazy: <.+> against <a><b> matches the whole string, because + takes as much as it can. <.+?> matches just <a>. This single character causes more regex bugs than anything else.

Groups & alternation

TokenMatchesExample
(abc)Capturing group - available as $1(\d{4})-(\d{2})
(?:abc)Non-capturing group - groups without numberingUse it when you only need the grouping
(?<year>\d{4})Named groupRead it back as groups.year
a|bEither a or b(jpg|png|gif)
\1Backreference to group 1(\w)\1 finds a doubled letter

Lookaround

TokenMatchesExample
(?=abc)Lookahead - followed by, without consuming\d+(?= USD) takes the number before " USD"
(?!abc)Negative lookahead - not followed by^(?!test) excludes lines starting with test
(?<=abc)Lookbehind - preceded by(?<=\$)\d+ takes the number after a $
(?<!abc)Negative lookbehind

Flags

g global

Find every match, not just the first. Required for replace-all and for iterating matches.

i ignore case

/abc/i matches ABC.

m multiline

Makes ^ and $ match at each line break instead of only at the ends of the string.

s dotAll

Lets . match newlines too - essential when matching across lines.

u unicode

Enables \p{...} property escapes and correct handling of astral characters like emoji.

y sticky

Match only at lastIndex - used by tokenizers.

Ready-made patterns

Pragmatic, not RFC-perfect. Paste any of these into the regex tester to try them.

GoalPatternNote
Email (practical)^[^\s@]+@[^\s@]+\.[^\s@]{2,}$Do not try to fully validate email with regex - send a confirmation instead.
UUID v4^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$The 4 and [89ab] pin the version and variant.
IPv4^((25[0-5]|2[0-4]\d|1?\d?\d)\.){3}(25[0-5]|2[0-4]\d|1?\d?\d)$Rejects 999.1.1.1, unlike \d{1,3}.
ISO date^\d{4}-\d{2}-\d{2}$Shape only - it still allows 2026-13-45.
Hex colour^#(?:[0-9a-f]{3}|[0-9a-f]{6})$With the i flag.
URL slug^[a-z0-9]+(?:-[a-z0-9]+)*$No leading, trailing or doubled hyphens.
Trim whitespace^\s+|\s+$Replace with the empty string, g flag.
Leading zeros^0+(?=\d)Strips zeros but keeps a lone 0.
Duplicate word\b(\w+)\s+\1\bFinds "the the".

Traps that bite in production

Catastrophic backtracking

Nested quantifiers like (a+)+$ can take exponential time on a non-matching input, hanging the thread. This is a real denial-of-service vector (ReDoS) whenever the pattern or the input comes from a user.

. stops at newlines

By default . never crosses a line break, so multi-line matches silently fail. Add the s flag.

Unescaped dots

file.txt as a pattern also matches fileXtxt. Escape it: file\.txt.

Emoji are two code units

Without the u flag, . matches half an emoji and produces broken output. See the test-string library.

Anchors with m

Forgetting m when validating multi-line input means ^ only matches once, at the very start.

Do not parse HTML

HTML is not a regular language; nesting defeats any pattern. Use a parser.

Try a pattern now

Open the regex tester Test strings →