The Regex Cheatsheet You'll Actually Come Back To
Nobody memorizes regular expressions. Even developers who use them weekly keep a mental model of maybe ten constructs and look up the rest. That's fine — regex is a lookup skill, not a memorization skill.
This cheatsheet covers two things: the core syntax you need to read any pattern, and 20 battle-tested patterns for problems that come up constantly. Paste any of them into a Regex Tester to see matches highlighted live before you trust them in code.
The 60-Second Syntax Refresher
Four building blocks explain 90% of every regex you'll ever read.
Character classes — what can match
| Syntax | Matches |
|---|---|
. | Any character (except newline) |
\d / \D | Digit / non-digit |
\w / \W | Word character (letters, digits, _) / non-word |
\s / \S | Whitespace / non-whitespace |
[abc] | Any of a, b, c |
[^abc] | Anything except a, b, c |
[a-z0-9] | Ranges: lowercase letter or digit |
Quantifiers — how many times
| Syntax | Meaning |
|---|---|
* | 0 or more |
+ | 1 or more |
? | 0 or 1 |
{3} | Exactly 3 |
{2,5} | Between 2 and 5 |
*? +? | Lazy versions — match as little as possible |
Anchors — where it matches
^ start of string, $ end of string, \b word boundary. Forgetting anchors is the #1 cause of "my validation regex accepts garbage": \d{4} happily matches inside abc12345xyz. Use ^\d{4}$ to validate a whole string.
Groups
(...)— capturing group, referenced as$1,$2in replacements(?:...)— non-capturing group (grouping without the capture overhead)(?<name>...)— named group,$<name>in JavaScript replacements(?=...)/(?!...)— lookahead: assert what follows without consuming it
If a pattern with nested groups makes your eyes glaze over, a Regex Visualizer renders it as a railroad diagram — often the fastest way to understand someone else's regex.
20 Copy-Paste Patterns
Validation
1. Email (pragmatic) — good enough for forms; true RFC 5322 validation needs an actual email:
^[^\s@]+@[^\s@]+\.[^\s@]+$
2. URL (http/https) — protocol, domain, optional path:
^https?:\/\/[\w.-]+\.[a-z]{2,}(\/\S*)?$
3. IPv4 address — each octet capped at 255, not just \d{1,3}:
^((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$
4. Date, ISO format (YYYY-MM-DD) — validates shape, not calendar logic (it accepts Feb 31):
^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$
5. Date, European format (DD/MM/YYYY):
^(0[1-9]|[12]\d|3[01])\/(0[1-9]|1[0-2])\/\d{4}$
6. Time, 24-hour (HH:MM):
^([01]\d|2[0-3]):[0-5]\d$
7. International phone (E.164) — + followed by 7–15 digits:
^\+[1-9]\d{6,14}$
8. UUID (v1–v5):
^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
9. Semver version string — major.minor.patch with optional pre-release/build:
^\d+\.\d+\.\d+(-[\w.]+)?(\+[\w.]+)?$
10. Hex color — #fff or #ffffff, with optional alpha:
^#([0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$
11. URL slug — lowercase, digits, single hyphens:
^[a-z0-9]+(-[a-z0-9]+)*$
12. Strong password — at least 8 chars, one lower, one upper, one digit, one special (lookaheads in action):
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\w\s]).{8,}$
Cleanup and extraction
13. Trailing whitespace — replace with nothing (multiline flag m):
[ \t]+$
14. Multiple spaces → one — replace with a single space:
{2,}
15. Duplicated word (the the) — backreference \1 plus word boundaries:
\b(\w+)\s+\1\b
16. Empty lines — collapse 2+ blank lines into one:
\n{3,}
17. HTML tags (strip) — the lazy quantifier keeps it from swallowing the whole document:
<[^>]+?>
18. Extract domain from URL:
^https?:\/\/(?:www\.)?([^\/:?#]+)
19. Numbers in a string — integers and decimals, with optional sign:
-?\d+(\.\d+)?
20. Text between quotes — non-greedy, handles multiple quoted segments per line:
"([^"]*)"
Patterns 13–16 shine in bulk text cleanup. A Find & Replace tool with regex support lets you run them across a whole document with capture-group substitutions like $1.
Two Warnings Before You Ship
Catastrophic backtracking
Nested quantifiers over overlapping character sets — the classic being (a+)+$ or (\w+\s?)*$ — can make the engine try an exponential number of paths on non-matching input. A 30-character string can hang your process. This is a real attack class (ReDoS): Cloudflare's 2019 global outage was one regex.
Rules of thumb: avoid nesting +/* inside another +/*, prefer specific classes ([^"] instead of .) so alternatives can't overlap, and always test patterns against long strings that almost match.
Don't parse HTML with regex
Pattern 17 above is fine for quick, one-off stripping of tags from trusted text. It is not an HTML parser. HTML allows nesting, comments containing >, attributes containing >, CDATA, and malformed-but-rendered markup — regex is structurally incapable of handling that (it can't count nesting depth). For anything beyond a quick cleanup, use a real parser: DOMParser in the browser, BeautifulSoup in Python, Cheerio in Node.
Building Your Own Patterns
When none of the 20 fit, work incrementally: start with a literal match, generalize one piece at a time, and re-test after every change. Write down 3–5 strings that should match and 3–5 that shouldn't — your negative cases catch more bugs than your positive ones.
And when the pattern you need is genuinely hairy — nested optional parts, multiple formats in one — describing it in plain English to an AI Regex Generator and then verifying the output against your test cases is faster than trial-and-error.
Test Your Regex Now
Paste any pattern from this cheatsheet into the Regex Tester and see matches, groups, and replacements highlighted in real time. No account required.