Regex Cheat Sheet: Patterns, Flags and Real-World Examples
A practical regular expression cheat sheet with character classes, quantifiers, anchors, groups, lookarounds, flags and tested patterns for everyday tasks.
· 5 min read
Regular expressions are a compact language for describing text. A single line can validate input, extract data from logs or rename hundreds of files. The syntax is dense, though, and small mistakes produce patterns that almost work. This cheat sheet collects the syntax you will use daily, explains the parts that trip people up, and ends with tested patterns you can adapt. All examples use JavaScript syntax, which is also very close to Python, Java, Go and .NET.
Try each pattern in a regex tester as you read; seeing matches highlighted is the fastest way to build intuition.
Literal characters and escaping
Most characters match themselves: cat matches "cat". Twelve characters have special meaning and must be escaped with a backslash to match literally:
. * + ? ^ $ { } ( ) | [ ] \ /
So 3.14 matches "3.14" but also "3x14", while 3\.14 matches only "3.14".
Character classes
| Pattern | Matches |
|---|---|
. |
Any character except a newline (unless the s flag is set) |
\d |
A digit 0–9 |
\w |
A word character: letter, digit or underscore |
\s |
Whitespace: space, tab, newline |
\D, \W, \S |
The opposite of the above |
[abc] |
One of a, b or c |
[a-z] |
Any lowercase ASCII letter |
[^0-9] |
Any character that is not a digit |
\p{L} |
Any letter in any script (requires the u flag) |
Inside square brackets, most special characters lose their meaning. [.] matches a literal dot. A hyphen is literal when placed first or last: [-a-z].
Quantifiers
| Pattern | Meaning |
|---|---|
a* |
Zero or more |
a+ |
One or more |
a? |
Zero or one (optional) |
a{3} |
Exactly three |
a{2,5} |
Between two and five |
a{2,} |
Two or more |
Quantifiers are greedy: they match as much as possible and then backtrack. Adding ? makes them lazy. Given <b>bold</b>, the pattern <.+> matches the entire string, while <.+?> matches only <b>.
Anchors and boundaries
^matches the start of the string, or of each line with themflag.$matches the end of the string, or of each line withm.\bmatches a word boundary: the position between a word character and a non-word character.
\bcat\b matches "cat" in "the cat sat" but not in "concatenate". Anchors are essential for validation: \d{5} finds five digits anywhere in "abc123456", while ^\d{5}$ requires the entire input to be exactly five digits.
Groups and alternation
(abc)groups and captures. Captured text is available as$1,$2in replacements.(?:abc)groups without capturing, which is faster and keeps numbering clean.(?<year>\d{4})is a named group, accessible asmatch.groups.year.a|bmatches a or b. Alternation has the lowest precedence, so^cat|dog$means "starts with cat" or "ends with dog". Use^(?:cat|dog)$to match exactly one of the words.\1is a backreference to group 1:(\w)\1finds doubled letters like "ll" in "hello".
Lookarounds
Lookarounds assert that something is or is not next to the current position without consuming characters.
| Pattern | Meaning |
|---|---|
(?=...) |
Positive lookahead: followed by |
(?!...) |
Negative lookahead: not followed by |
(?<=...) |
Positive lookbehind: preceded by |
(?<!...) |
Negative lookbehind: not preceded by |
Examples: \d+(?=px) matches the number in "16px" without "px"; (?<=\$)\d+ matches the amount after a dollar sign; ^(?!.*password).*$ matches lines that do not contain "password".
Flags
g(global): find all matches instead of stopping at the first.i(ignore case):amatches "A".m(multiline):^and$match at line breaks.s(dotAll):.also matches newlines.u(unicode): treats surrogate pairs such as emoji as single characters and enables\p{...}.y(sticky): matches only at the position where the last match ended.
Patterns for everyday tasks
These are practical rather than exhaustive. Real validation should be combined with server-side checks.
Email (pragmatic):
^[^\s@]+@[^\s@]+\.[^\s@]{2,}$
Catches typos like a missing @ or domain; the only real validation is sending a confirmation email.
URL slug:
^[a-z0-9]+(?:-[a-z0-9]+)*$
ISO date (YYYY-MM-DD):
^(?<year>\d{4})-(?<month>0[1-9]|1[0-2])-(?<day>0[1-9]|[12]\d|3[01])$
This checks shape and ranges but not whether 31 February exists; parse the date to confirm.
Hex colour:
^#(?:[0-9a-fA-F]{3}){1,2}$
IPv4 address:
^(?:(?:25[0-5]|2[0-4]\d|1?\d?\d)\.){3}(?:25[0-5]|2[0-4]\d|1?\d?\d)$
Semantic version:
^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[\w.-]+)?(?:\+[\w.-]+)?$
Strong password check (at least 12 characters, one lowercase, one uppercase, one digit):
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{12,}$
Trim whitespace: replace ^\s+|\s+$ (with g) with an empty string.
Collapse repeated spaces: replace {2,} with a single space.
Extract key=value pairs from a log line:
(\w+)=("[^"]*"|\S+)
camelCase to snake_case: replace ([a-z0-9])([A-Z]) with $1_$2, then lowercase the result. For more on naming styles, see camelCase vs snake_case.
Performance and catastrophic backtracking
Regex engines in JavaScript, Python and Java use backtracking. Some patterns force the engine to try an exponential number of combinations on inputs that almost match. The classic example is ^(a+)+$ against "aaaaaaaaaaaaaaaaaaaaaaaa!". Each extra "a" doubles the work, and a few dozen characters can freeze a server — a denial-of-service vector known as ReDoS.
To avoid it:
- Do not nest quantifiers over the same characters, as in
(a+)+or(\w*)*. - Make alternatives mutually exclusive:
(a|ab)*is risky; restructure it. - Prefer specific classes over
.*:"[^"]*"is safer and faster than".*?". - Limit input length before matching untrusted data.
Readability tips
- Build complex patterns incrementally and test each piece.
- Use named groups so code reads
m.groups.monthrather thanm[2]. - Comment complicated patterns in code, or build them from smaller strings.
- If a pattern needs more than a line or two, consider whether a small parser would be clearer.
Summary
Learn the core — classes, quantifiers, anchors, groups and flags — and you can read most regexes you encounter. Use lazy quantifiers and anchors deliberately, reach for lookarounds when you need context without consuming it, watch for nested quantifiers, and always test against both matching and non-matching examples before shipping a pattern.