Regex Cheat Sheet — The Patterns You'll Actually Use
This is the regex reference you keep open while you work: the syntax that comes up daily, a set of copy-ready patterns, and — the part most cheat sheets skip — the traps that waste your afternoon. Test anything here live in the free Regex Tester, which highlights matches as you type, breaks out your capture groups, and previews replacements. (Everything below is JavaScript/ECMAScript flavor; see the cross-language note at the end.)
On this page
Character classes
| Token | Matches |
|---|---|
. |
Any character except newline |
\d / \D |
A digit [0-9] / a non-digit |
\w / \W |
A word char [A-Za-z0-9_] / a non-word char |
\s / \S |
Whitespace / non-whitespace |
[abc] |
Any one of a, b, c |
[^abc] |
Any char except a, b, c |
[a-z] |
A range (lowercase letter) |
Anchors
| Token | Matches |
|---|---|
^ |
Start of string (or line, with the m flag) |
$ |
End of string (or line, with m) |
\b / \B |
A word boundary / a non-boundary |
\b is the one people forget — it's why \bcat\b matches "cat" but not "category."
Quantifiers (and the greedy-vs-lazy trap)
| Token | Means |
|---|---|
* |
0 or more |
+ |
1 or more |
? |
0 or 1 (optional) |
{n} |
Exactly n |
{n,} |
n or more |
{n,m} |
Between n and m |
*? +? ?? |
The lazy versions (match as few as possible) |
By default quantifiers are greedy — they grab as much as they can. This is the classic bug: on <b>hello</b>, the pattern <.*> matches the whole string (first < to last >), while <.*?> (lazy) matches just <b>. Rule: when matching between delimiters — quotes, brackets, tags — use the lazy version.
Groups and alternation
| Token | Means |
|---|---|
(...) |
Capture group (extract it later) |
(?:...) |
Non-capturing group (group without storing) |
(?<name>...) |
Named capture group |
(a|b) |
Alternation — a or b |
\1, \k<name> |
Backreference to a captured group |
If you don't need to extract a group, make it non-capturing (?:...) — it's cleaner and slightly faster.
Lookarounds (zero-width — they match a position, not characters)
| Token | Means |
|---|---|
(?=...) |
Positive lookahead — followed by |
(?!...) |
Negative lookahead — not followed by |
(?<=...) |
Positive lookbehind — preceded by |
(?<!...) |
Negative lookbehind — not preceded by |
Example: (?<=\$)\d+ grabs 199 from $199 without including the $. Lookarounds are how password rules work too: (?=.*\d) means "contains a digit somewhere" without consuming anything.
Flags
| Flag | Effect |
|---|---|
g |
Global — find all matches, not just the first |
i |
Case-insensitive |
m |
Multiline — ^/$ match line starts/ends |
s |
Dotall — . also matches newlines |
u |
Unicode mode |
y |
Sticky — match from lastIndex only |
The g flag is the one that surprises people: without it you get only the first match; with it you get them all. The Regex Tester has toggle buttons for every flag, so you can flip g/i/m and watch the matches change.
Ready-to-use patterns (test before you ship)
| Need | Pattern |
|---|---|
| Digits only | ^\d+$ |
| Hex color | ^#?([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$ |
| US ZIP | ^\d{5}(-\d{4})?$ |
| ISO date (YYYY-MM-DD) | ^\d{4}-\d{2}-\d{2}$ |
| Slug | ^[a-z0-9]+(?:-[a-z0-9]+)*$ |
| Strong password (8+, upper, digit, symbol) | ^(?=.*[A-Z])(?=.*\d)(?=.*[^\w\s]).{8,}$ |
| Duplicated word | \b(\w+)\s+\1\b |
On matching an email: you'll see a "perfect email regex" everywhere — don't trust it. A fully RFC-correct email regex is monstrous and still rejects valid addresses. For real validation, a loose check like ^[^@\s]+@[^@\s]+\.[^@\s]+$ plus actually sending a confirmation email beats any clever pattern. Regex tells you it looks like an email, not that it works.
The gotchas that cost you time
- Escape special characters to match them literally: a literal dot is
\., a literal?is\?. Forgetting this is the #1 regex bug. - Catastrophic backtracking (ReDoS): nested quantifiers like
(a+)+bcan hang on long non-matching input — a real denial-of-service risk on user input. Avoid nesting quantifiers; rewrite or anchor instead. - Don't parse HTML, XML, or JSON with regex. They're nested/recursive; regex isn't built for that and will break on edge cases. Use a real parser — for JSON, the JSON Formatter validates far more reliably than any pattern.
- Build incrementally. Test each piece in the Regex Tester before combining — a 60-character pattern you wrote in one go is a debugging nightmare.
Is regex the same in every language?
The core — character classes, quantifiers, anchors, basic groups — is consistent. The advanced bits differ: lookbehind, named groups, Unicode escapes, and flag syntax vary between JavaScript, Python (re), Java, Go, and PCRE. This cheat sheet is JavaScript flavor; if you're in another language, the basics carry over but check its docs for the fancy features.