Regex Cheat Sheet: Patterns, Flags & Examples
September 26, 2026 · Web Development
A regular expression (regex) is a tiny language for describing text patterns: \d+ means "one or more digits", ^[a-z]+$ means "a whole string of lowercase letters". This cheat sheet covers the 20% of regex you'll use 95% of the time — with examples you can steal and the honest caveats most cheat sheets skip.
The essentials: literals, dot, and character classes
| Pattern | Matches | Example |
|---|---|---|
abc | Literal text | abc matches "abc" |
. | Any character except newline | a.c matches "abc", "a_c" |
\d | Any digit (0–9) | \d\d matches "42" |
\w | Word char: letters, digits, _ | \w+ matches "hello_1" |
\s | Whitespace (space, tab, newline) | a\sb matches "a b" |
[abc] | Any one of a, b, c | [aeiou] matches a vowel |
[^abc] | Anything except a, b, c | [^0-9] matches non-digit |
[a-z] | Any char in the range | [A-Za-z] any letter |
Capital versions negate: \D is a non-digit, \W a non-word char, \S non-whitespace. Inside [...], most special characters lose their magic — [.] is a literal dot, no backslash needed.
Test as you learn: paste any pattern from this page into our free Regex Tester and watch matches highlight live, with capture groups broken out.
Quantifiers: how many?
| Pattern | Meaning | Example |
|---|---|---|
* | Zero or more | ab*c matches "ac", "abc", "abbbc" |
+ | One or more | \d+ matches "7", "007" |
? | Zero or one (optional) | colou?r matches "color", "colour" |
{3} | Exactly 3 | \d{3} matches "123" |
{2,4} | Between 2 and 4 | \w{2,4} matches "hi"–"test" |
{2,} | 2 or more | a{2,} matches "aa", "aaaa" |
Greedy vs lazy is the classic confusion: quantifiers are greedy by default — they consume as much as possible. <.*> on <b>hi</b> matches the whole string, not just <b>. Add ? to make it lazy (match as little as possible): <.*?> matches <b> then </b> separately. When a pattern "matches too much", laziness is usually the fix.
Anchors and boundaries
| Pattern | Meaning |
|---|---|
^ | Start of string (or line with m flag) |
$ | End of string (or line with m flag) |
\b | Word boundary |
\bcat\b matches "cat" but not "concatenate" — the boundary sits between a word char and a non-word char. And remember: without ^...$ anchors, your pattern matches anywhere in the string. \d+ "validates" "abc123" as containing digits — which is rarely what validation means.
Groups, alternation, and backreferences
| Pattern | Meaning | Example |
|---|---|---|
(abc) | Group + capture | (\d+)-(\d+) captures both number groups |
(?:abc) | Group without capturing | Faster; use when you don't need the parts |
a|b | Either a or b | cat|dog matches either word |
(?<year>\d{4}) | Named group | Refer to it as "year" instead of group 1 |
\1 | Backreference to group 1 | (\w+)\s+\1 finds doubled words |
Alternation has the lowest precedence: ^cat|dog$ means (^cat)|(dog$), not ^(cat|dog)$. When in doubt, add parentheses — explicit grouping beats precedence memorization.
Flags: the little letters that change everything
| Flag | Name | Effect |
|---|---|---|
g | Global | Find all matches, not just the first |
i | Ignore case | cat matches "CAT" |
m | Multiline | ^/$ match line boundaries |
s | Dot-all | . matches newlines too |
Copy-paste patterns that actually work
| Use | Pattern | Honest caveat |
|---|---|---|
^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$ | Catches typos; not RFC-complete (good — see FAQ) | |
| URL | https?://[^\s/$.?#].[^\s]* | Pragmatic; full URL validation is a rabbit hole |
| Date (YYYY-MM-DD) | ^\d{4}-\d{2}-\d{2}$ | Shape only — "2026-99-99" passes; validate ranges in code |
| Hex color | ^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$ | Covers #RGB and #RRGGBB |
| Slug | ^[a-z0-9]+(?:-[a-z0-9]+)*$ | Lowercase words joined by single hyphens |
| IPv4 (shape) | ^(?:\d{1,3}\.){3}\d{1,3}$ | Allows 999.999.999.999; range-check separately |
Paste any of these into the Regex Tester with sample text — including text that should not match — before trusting them.
Three traps to memorize
- Escaping in code strings: the string parser eats backslashes before regex sees them. In JavaScript
"\\d"is fine in a regex literal/\d/but needs doubling innew RegExp("\\d"). Python raw strings (r"\d") exist precisely for this. - Flavor differences: lookbehind, named groups, and Unicode property escapes (
\p{L}) exist in modern JavaScript but not everywhere; Python's(?P<name>...)isn't JS syntax. Test in your deployment engine. - Catastrophic backtracking: nested quantifiers like
(a+)+$can hang on non-matching input. If a pattern ever freezes, this is almost always why — rewrite with more specific character classes.
Frequently asked questions
- What is regex used for?
- Validating input (emails, phone numbers), extracting structured bits from messy text (dates, IDs, prices from logs), and find-and-replace with patterns across codebases. If the task is "find text shaped like X", regex is usually the right tool.
- What's the difference between * and +?
- `*` means zero or more of the preceding element; `+` means one or more. So `\d*` matches an empty string (it's happy with zero digits), while `\d+` requires at least one digit. This is the single most common source of "why did it match nothing?" bugs.
- How do I validate an email with regex?
- Use a pragmatic pattern like `^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$` — it catches typos and malformed input. Don't chase a "perfect" email regex; the RFC allows bizarre addresses no regex should try to bless. Validate shape with regex, verify ownership by sending an email.
- What do ^ and $ do?
- `^` anchors a match to the start of the string (or line, with the multiline flag) and `$` anchors to the end. `^\d+$` means "the entire string is digits" — without anchors, `\d+` happily matches the digits inside "abc123".
- Why isn't my regex matching across newlines?
- Two usual causes: the dot `.` doesn't match newlines by default (enable the dot-all flag `s`), or `^`/`$` are matching string boundaries instead of line boundaries (enable multiline `m`). Check which one your pattern actually needs.
- Are regex flavors different?
- Yes — JavaScript, Python, PCRE (PHP), Go, and Java each support a different feature set. Named-group syntax, lookbehind support, and inline flags all vary. Always test in the engine you'll deploy, not just the one you learned in.
- How do I escape special characters?
- Prefix with a backslash: `\.` for a literal dot, `\$`, `\(`, etc. Inside a character class `[...]` most specials lose their meaning, but `]`, `\`, `^` (first), and `-` (between chars) still need care. In code strings, remember the string itself may eat a backslash first — `"\\d"` in many languages is the regex `\d`.
Related articles
Base64 Encoding Explained: How It Works & When to Use It
What base64 really does, why it inflates data by 33%, base64 vs base64url, and when to reach for it — and when not to.
Web DevelopmentUUID v4 vs v7: Which Version Should You Use?
Random vs time-ordered UUIDs: how v7 fixes database index fragmentation, and when v4 is still the right call.
Web DevelopmentURL Encoding (Percent-Encoding) Explained
Why spaces become %20, when to encode (and what never to encode), plus the classic + vs %20 and double-encoding traps.