Regex Cheat Sheet

Regular expressions have hundreds of features, and day-to-day work uses perhaps thirty tokens. This page is those thirty: what each one means, what it matches, and where it bites. Everything here uses JavaScript syntax, which is close enough to Python, Go and PCRE that the differences rarely matter. You can test any of it live in the Regex Tester: paste a pattern, paste some text, and watch the matches highlight as you type.

Character classes

A character class matches exactly one character out of a set. The uppercase variants negate their lowercase twins.

TokenMeaningExample match
\da digit 0–97 in v7
\Danything but a digitv in v7
\wword character: letter, digit or _a, 9, _
\Wanything but a word character-, a space
\swhitespace: space, tab, newlinethe gap in a b
\Sanything but whitespacex
.any character except newlinea, ?, 7
[a-f0-9]one character from a custom rangec, 4
[^a-z]negation: anything not in the setQ, 3

Inside [...] most special characters lose their powers, so [.+?] matches a literal dot, plus or question mark. The exceptions are ], \, a ^ at the start, and - between two characters.

Quantifiers

TokenMeaningExample match
*zero or morea* matches "", aaa
+one or more\d+ matches 2026
?zero or onecolou?r matches both spellings
{3}exactly n\d{3} matches 404
{2,4}between n and ma{2,4} matches aa to aaaa
{2,}n or morex{2,} matches xxxxx

Quantifiers are greedy by default and grab as much as they can. Against <b>hi</b>, the pattern <.+> matches the entire string, because .+ runs all the way to the last > it can find. Append ? and the quantifier turns lazy: <.+?> stops at the first > and matches just <b>. Nine out of ten “my regex matches too much” bugs are a greedy quantifier that needed to be lazy.

Anchors and boundaries

Anchors match positions rather than characters. ^ is the start of the string and $ the end, and with the m flag they become the start and end of each line instead. \b is a word boundary, the seam between a \w character and a non-word character, so \bcat\b matches cat but not concatenate. Forgetting anchors is the classic validation bug: \d+ happily “validates” abc123def, while ^\d+$ does not.

Groups and alternation

TokenMeaningExample
(...)capturing group, referenced by number(\d+)px captures 16
(?:...)non-capturing group, for grouping only(?:ab)+
(?<name>...)named group(?<year>\d{4})
\1backreference: match group 1’s text again("|')\1 matches paired quotes
a|balternation: a or bcat|dog

Alternation has the lowest precedence of anything in the language, so ^cat|dog$ reads as “starts with cat, or ends with dog,” which is almost never what anyone means. Write ^(?:cat|dog)$ instead. Use (?:...) whenever you only need grouping: it keeps capture numbers stable and is marginally faster.

Lookarounds

Lookarounds assert what surrounds a position without consuming it. The matched text stays untouched, which is what makes them ideal for surgical find-and-replace.

TokenMeaningExample
(?=...)lookahead: followed by\d+(?=px) matches 16 in 16px
(?!...)negative lookahead: not followed by\d+(?!px)
(?<=...)lookbehind: preceded by(?<=\$)\d+ matches 25 in $25
(?<!...)negative lookbehind: not preceded by(?<!\$)\d+

Flags

FlagEffect
gglobal: find all matches, not just the first
icase-insensitive
mmultiline: ^ and $ anchor at every line
sdotall: . also matches newlines
uUnicode mode: correct handling of emoji and \p{...} classes
ysticky: match must start exactly at lastIndex

Copy-paste recipes

Five patterns that cover a surprising share of real work. Each one is deliberately pragmatic, and the caveats are part of the recipe.

^[^\s@]+@[^\s@]+\.[^\s@]+$

Email, the pragmatic version: something, an @, something, a dot, something. A fully RFC-compliant email regex is a fool’s errand. The “correct” one runs to thousands of characters and still cannot tell you whether the mailbox exists, so check the shape and then send a confirmation email.

https?:\/\/[^\s"'<>]+

Extracts http and https URLs from free text. It finds URLs; it does not validate them, and it will cheerfully swallow a trailing ) or comma if the surrounding prose supplies one.

^\d{4}-\d{2}-\d{2}$

ISO 8601 date shape (2026-07-25), and shape only. 2026-13-99 passes, so parse it with a real date library afterwards.

[ \	]+$

Trailing whitespace. Run it with the gm flags and replace with nothing to clean every line. Handy before comparing files in the Text Diff tool, where invisible trailing spaces otherwise show up as changed lines.

\b(\w+)\s+\1\b

Duplicate adjacent words (“the the”), caught with a backreference. Add the gi flags so “The the” is found too. It only sees exact repeats separated by whitespace.

None of this needs memorizing. Keep the tables handy, and when a pattern misbehaves, drop it into the Regex Tester with a failing example. Watching the highlight change as you edit is the fastest regex debugger there is.

Sources and further reading