The Complete Regex Cheat Sheet for Web Developers
Regular expressions are one of the most powerful—and most feared—tools in a developer's arsenal. A single line of regex can replace dozens of lines of string manipulation code. But the syntax is dense, the edge cases are numerous, and catastrophic backtracking can bring a server to its knees. This complete cheat sheet covers everything from basic anchors to advanced lookaheads, plus 10 real-world patterns you can use immediately.
Test every pattern in this guide using our Regex Tester—it shows matches, groups, and flags in real time.
Anchors and Boundaries
Anchors do not match characters—they match positions in the string.
| Pattern | Meaning | Example |
|---|---|---|
^ | Start of string (or line with m flag) | /^Hello/ matches "Hello world" but not "Say Hello" |
$ | End of string (or line with m flag) | /world$/ matches "Hello world" but not "world peace" |
\b | Word boundary (transition between \w and \W) | /\bcat\b/ matches "cat" but not "concatenate" |
\B | Non-word boundary | /\Bcat\B/ matches "concatenate" but not standalone "cat" |
\A | Start of string (Python/PHP, not JS) | — |
\Z | End of string (Python/PHP, not JS) | — |
Character Classes
| Pattern | Meaning |
|---|---|
\d | Digit: [0-9] |
\D | Non-digit: [^0-9] |
\w | Word character: [A-Za-z0-9_] |
\W | Non-word character |
\s | Whitespace: space, tab, newline, carriage return, form feed |
\S | Non-whitespace |
. | Any character except newline (unless s flag is set) |
[abc] | Character set: a, b, or c |
[^abc] | Negated set: anything except a, b, or c |
[a-z] | Range: lowercase a through z |
[a-zA-Z0-9] | Multiple ranges combined |
Quantifiers
| Pattern | Meaning |
|---|---|
* | 0 or more (greedy) |
+ | 1 or more (greedy) |
? | 0 or 1 (greedy) |
{n} | Exactly n times |
{n,} | n or more times |
{n,m} | Between n and m times (inclusive) |
*? | 0 or more (lazy—matches as few as possible) |
+? | 1 or more (lazy) |
?? | 0 or 1 (lazy) |
Greedy vs Lazy Matching
Greedy quantifiers consume as much input as possible and then backtrack. Lazy quantifiers consume as little as possible. This distinction is critical when matching HTML-like structures:
const html = 'bold and more bold';
// Greedy: matches from first < to last > (entire string!)
const greedy = html.match(/.*<\/b>/);
// Result: 'bold and more bold'
// Lazy: matches from first < to nearest >
const lazy = html.match(/.*?<\/b>/);
// Result: 'bold'
Groups and References
Capturing groups (...) capture matched text for backreferences or extraction.
Named capture groups (?<name>...) make captures readable and accessible by name:
const dateStr = '2026-04-12';
const dateRegex = /(?\d{4})-(?\d{2})-(?\d{2})/;
const match = dateStr.match(dateRegex);
console.log(match.groups.year); // "2026"
console.log(match.groups.month); // "04"
console.log(match.groups.day); // "12"
// Named groups in replace
'2026-04-12'.replace(dateRegex, '$/$/$');
// "12/04/2026"
Non-capturing groups (?:...) group without capturing—more efficient when you don't need the captured value:
// Captures "https" or "http" in group 1
/https?:\/\/(\w+)/
// Groups alternation without capturing
/(?:https?|ftp):\/\/(\w+)/
Lookahead and Lookbehind
Lookaheads and lookbehinds are zero-width assertions—they check for a pattern without including it in the match.
// Positive lookahead (?=...) - matches if followed by pattern
/\d+(?= dollars)/.exec('100 dollars'); // "100"
/\d+(?= dollars)/.exec('100 euros'); // null
// Negative lookahead (?!...) - matches if NOT followed by pattern
/\d+(?! dollars)/.exec('100 euros'); // "100"
// Positive lookbehind (?<=...) - matches if preceded by pattern
/(?<=\$)\d+/.exec('$100'); // "100"
// Negative lookbehind (?
Flags
| Flag | Name | Effect |
|---|---|---|
g | Global | Find all matches, not just the first |
i | Case-insensitive | /hello/i matches "Hello", "HELLO", etc. |
m | Multiline | ^ and $ match start/end of each line |
s | DotAll | . matches newlines too |
u | Unicode | Enables full Unicode matching; required for emoji and astral characters |
y | Sticky | Match only at lastIndex position; useful for tokenizers |
d | Indices | Adds indices array to match result with start/end positions |
10 Real-World Regex Patterns
1. Email Validation
// Practical email validation (not RFC 5322 complete, but covers 99% of cases)
const emailRegex = /^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$/;
emailRegex.test('user@example.com'); // true
emailRegex.test('user+tag@sub.co.uk'); // true
emailRegex.test('not-an-email'); // false
2. URL Matching
const urlRegex = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&/=]*)/;
urlRegex.test('https://example.com/path?q=1'); // true
urlRegex.test('http://sub.domain.co.uk'); // true
3. IPv4 Address
const ipv4Regex = /^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$/;
ipv4Regex.test('192.168.1.1'); // true
ipv4Regex.test('256.0.0.1'); // false
4. ISO 8601 Date
const isoDateRegex = /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])(T([01]\d|2[0-3]):[0-5]\d:[0-5]\d(\.\d+)?(Z|[+-][01]\d:[0-5]\d))?$/;
isoDateRegex.test('2026-04-12'); // true
isoDateRegex.test('2026-04-12T14:30:00Z'); // true
5. Hex Color
const hexColorRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/;
hexColorRegex.test('#FF5733'); // true
hexColorRegex.test('#f57'); // true
hexColorRegex.test('#GGGGGG'); // false
6. Semantic Version
const semverRegex = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
semverRegex.test('1.2.3'); // true
semverRegex.test('2.0.0-alpha.1'); // true
semverRegex.test('1.0'); // false
7. Credit Card Masking
// Mask middle digits of a credit card number
'4111111111111111'.replace(/(\d{4})\d{8}(\d{4})/, '$1 **** **** $2');
// "4111 **** **** 1111"
8. URL Slug Validation
const slugRegex = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
slugRegex.test('my-blog-post'); // true
slugRegex.test('My Blog Post'); // false
slugRegex.test('-starts-with-dash'); // false
9. HTML Tag Stripping
// Warning: not safe for sanitization—use a proper HTML sanitizer for security
function stripTags(html) {
return html.replace(/<[^>]*>/g, '');
}
stripTags('Hello world
'); // "Hello world"
10. Password Strength Check
function checkPasswordStrength(password) {
const hasLength = password.length >= 12;
const hasUpper = /[A-Z]/.test(password);
const hasLower = /[a-z]/.test(password);
const hasDigit = /\d/.test(password);
const hasSpecial = /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(password);
const score = [hasLength, hasUpper, hasLower, hasDigit, hasSpecial]
.filter(Boolean).length;
return { score, hasLength, hasUpper, hasLower, hasDigit, hasSpecial };
}
ReDoS: Catastrophic Backtracking
ReDoS (Regular Expression Denial of Service) occurs when a regex takes exponential time to match (or fail to match) certain inputs. The classic example:
// DANGEROUS: Exponential backtracking
const dangerous = /^(a+)+$/;
// With input "aaaaaaaaaaaaaaab" (15 a's followed by 'b')
// The regex engine tries 2^15 = 32,768 combinations before failing
dangerous.test('aaaaaaaaaaaaaaab'); // Hangs the process
The risk patterns are nested quantifiers ((a+)+), alternation inside quantifiers ((a|aa)+), and overlapping character classes in quantified groups. Tools like ReDoS checker can detect vulnerable patterns. Alternatively, use Node.js's --experimental-vm-modules with a timeout, or the re2 npm package which uses Google's RE2 engine (linear time guaranteed).
Engine Differences: JavaScript vs Python vs PHP
Not all regex engines are equal:
- JavaScript: ECMA flavor, uses NFA engine, supports named captures (
(?<name>)), lookbehind added in ES2018. No possessive quantifiers. No\p{}Unicode properties without theuflag. - Python: Uses the
remodule (NFA based). Named groups use(?P<name>)syntax. The newerregexmodule adds possessive quantifiers and atomic groups. - PHP: Uses PCRE2 (Perl Compatible Regular Expressions). Supports possessive quantifiers (
++,*+), atomic groups(?>...), and Unicode properties. Most powerful of the three for advanced patterns.
Use our Text Diff tool to compare regex output across different test cases, and the Regex Tester to build and debug patterns interactively.