Regex Cheat Sheet 2026: The Only Reference You Need
Bookmark this page. Every developer needs a regex reference they can scan in 30 seconds. This one covers the syntax, the common patterns, and the language-specific differences that trip people up.
Character Classes
| Pattern | Matches | Example |
. | Any character except newline | a.c matches abc, a1c |
\d | Digit (0-9) | \d{3} matches 123 |
\D | Non-digit | \D+ matches abc |
\w | Word character (a-z, A-Z, 0-9, _) | \w+ matches hello_world |
\W | Non-word character | \W matches @ |
\s | Whitespace (space, tab, newline) | \s+ matches |
\S | Non-whitespace | \S+ matches hello |
[abc] | Any of a, b, or c | [aeiou] matches vowels |
[^abc] | Not a, b, or c | [^0-9] matches non-digits |
[a-z] | Range: a through z | [A-Za-z] matches letters |
Quantifiers
| Pattern | Meaning | Example |
| 0 or more | \d matches "", "123" |
+ | 1 or more | \d+ matches "123" but not "" |
? | 0 or 1 | colou?r matches color, colour |
{3} | Exactly 3 | \d{3} matches 123 |
{2,5} | 2 to 5 | \w{2,5} matches hi, hello |
{2,} | 2 or more | \d{2,} matches 12, 123456 |
? | 0 or more (lazy) | ".?" matches first quoted string |
+? | 1 or more (lazy) | <.+?> matches single HTML tag |
Greedy vs Lazy: By default, * and + are greedy (match as much as possible). Adding ? makes them lazy (match as little as possible). This matters most when matching quoted strings or HTML tags.
Anchors and Boundaries
| Pattern | Meaning |
^ | Start of string (or line with m flag) |
$ | End of string (or line with m flag) |
\b | Word boundary |
\B | Not a word boundary |
\bcat\b matches "cat" in "the cat sat"
does NOT match "cat" in "concatenate"
Groups and Backreferences
| Pattern | Meaning | Example |
(abc) | Capturing group | (ha)+ matches hahaha | ||
(?:abc) | Non-capturing group | (?:ha)+ same match, no capture | ||
(? | Named group | (? | ||
\1 | Backreference to group 1 | (\w+)\s\1 matches the the | ||
(a\ | b) | Alternation (a or b) | (cat\ | dog) matches either |
Lookahead and Lookbehind
| Pattern | Meaning | Example |
(?=abc) | Positive lookahead | \d+(?=px) matches 12 in 12px |
(?!abc) | Negative lookahead | \d+(?!px) matches 12 in 12em |
(?<=abc) | Positive lookbehind | (?<=\$)\d+ matches 50 in $50 |
(? | Negative lookbehind | (? matches |
Lookarounds are zero-width assertions -- they check for a pattern without consuming characters.
Common Patterns
Email Address
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
This covers 99% of valid email addresses. For true RFC 5322 compliance, the regex is absurdly long and you should use a library instead.
URL
https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)
IP Address (IPv4)
\b(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\b
The naive \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} matches invalid IPs like 999.999.999.999. The pattern above validates each octet is 0-255.
Phone Number (US)
^(\+1)?[-.\s]?\(?[0-9]{3}\)?[-.\s]?[0-9]{3}[-.\s]?[0-9]{4}$
Matches: 555-123-4567, (555) 123-4567, +1 555.123.4567
Date (YYYY-MM-DD)
^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$
Password Strength (min 8 chars, upper + lower + digit + special)
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$
This uses four lookaheads to require one of each character type.
UUID v4
^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
Hex Color
^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$
Slug (URL-friendly string)
^[a-z0-9]+(?:-[a-z0-9]+)*$
Language-Specific Differences
JavaScript
// Literal syntax
const re = /\d+/g;
// Constructor (for dynamic patterns)
const re2 = new RegExp('\\d+', 'g');
// Methods
'hello 123'.match(/\d+/); // ['123']
'hello 123'.replace(/\d+/, 'NUM'); // 'hello NUM'
/\d+/.test('hello 123'); // true
// Named groups
const m = '2025-03-15'.match(/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/);
m.groups.year; // '2025'
// matchAll (returns iterator)
const matches = [...'a1 b2 c3'.matchAll(/([a-z])(\d)/g)];
JS-specific flags: d (indices), s (dotAll -- . matches newline), u (unicode), v (unicodeSets, new in ES2024).
Python
import re
# Search (first match)
m = re.search(r'\d+', 'hello 123 world 456')
m.group() # '123'
# Find all
re.findall(r'\d+', 'hello 123 world 456') # ['123', '456']
# Replace
re.sub(r'\d+', 'NUM', 'hello 123') # 'hello NUM'
# Compile for reuse
pattern = re.compile(r'(?P<year>\d{4})-(?P<month>\d{2})')
m = pattern.match('2025-03')
m.group('year') # '2025'
# Verbose mode (for readable complex patterns)
pattern = re.compile(r'''
^(?P<protocol>https?):// # protocol
(?P<domain>[^/]+) # domain
(?P<path>/.*)?$ # path (optional)
''', re.VERBOSE)
Python uses (?P for named groups (not (? like JS).
Go
import "regexp"
re := regexp.MustCompile(`\d+`)
re.FindString("hello 123") // "123"
re.FindAllString("a1 b2 c3", -1) // ["1", "2", "3"]
re.ReplaceAllString("hello 123", "N") // "hello N"
Go does not support lookaheads or lookbehinds. The regexp package uses RE2 syntax, which guarantees linear-time matching but sacrifices some features. If you need lookarounds in Go, restructure your approach or use multiple passes.
Testing Your Regex
Before deploying a regex, test it against edge cases. regex101.com is the standard -- it shows matches in real time, explains each part of the pattern, and lets you switch between PCRE, JavaScript, Python, and Go flavors.
devdash.io also has a regex tester with a simpler interface if you just need quick validation without the full breakdown.
For unit testing, always test these edge cases:
- Empty string
- String with only whitespace
- Unicode characters (accented letters, emoji)
- Very long strings (check for catastrophic backtracking)
- Strings that almost match but should not
Performance: Avoiding Catastrophic Backtracking
This regex looks harmless but can freeze your program:
(a+)+b
On input aaaaaaaaaaaaaaaaac, the engine backtracks exponentially. This is called "catastrophic backtracking" or "ReDoS."
Rules to avoid it:
- Never nest quantifiers (
(a+)+,(a)) - Use atomic groups or possessive quantifiers when available
- Be specific --
[a-z]+is safer than.* - Set a timeout on regex execution in production code
- Test with long non-matching strings, not just matching ones
Regex is powerful but it is a sharp tool. Write the simplest pattern that matches your requirements, test it thoroughly, and add a comment explaining what it does. Your future self will thank you.