Toolmingo
Guides8 min read

Regex Cheat Sheet: Every Pattern You Actually Need

A complete regular expressions cheat sheet: character classes, quantifiers, anchors, groups, lookaheads, flags, and ready-to-copy patterns for email, URL, date, IP address, and more.

Bookmarked and referenced dozens of times per project — this is the regular expressions reference that covers everything from the basics to the patterns you reach for in real code.

Character classes

Match a set or type of character.

Pattern What it matches
[abc] Any one of: a, b, or c
[a-z] Any lowercase letter
[A-Z] Any uppercase letter
[0-9] Any digit
[a-zA-Z0-9] Any letter or digit
[^abc] Any character except a, b, c (^ inside [] negates)
. Any character except newline
\d Digit — equivalent to [0-9]
\D Non-digit — equivalent to [^0-9]
\w Word character — [a-zA-Z0-9_]
\W Non-word character — [^\w]
\s Whitespace (space, tab, newline, carriage return)
\S Non-whitespace

Quantifiers

Control how many times the preceding element repeats.

Pattern Meaning
* 0 or more times
+ 1 or more times
? 0 or 1 time (makes preceding element optional)
{n} Exactly n times
{n,} n or more times
{n,m} Between n and m times (inclusive)

Greedy vs lazy: By default quantifiers are greedy — they match as much as possible. Add ? after any quantifier to make it lazy (match as little as possible).

"<b>bold</b> and <i>italic</i>"

Greedy:  <.+>   → matches entire string from first < to last >
Lazy:    <.+?>  → matches each tag individually: <b>, </b>, <i>, </i>

Anchors

Assert position without consuming characters.

Pattern Matches at
^ Start of string (or start of line in multiline mode)
$ End of string (or end of line in multiline mode)
\b Word boundary (between \w and \W)
\B Non-word boundary
\A Absolute start of string (Python, Java, Ruby — not JS)
\Z Absolute end of string (Python, Java, Ruby)
^\d{4}$         matches a string that is exactly 4 digits
\bword\b        matches "word" but not "password" or "wording"

Groups and alternation

Pattern Meaning
(abc) Capturing group — matches and captures "abc"
(?:abc) Non-capturing group — matches but doesn't capture
(?<name>abc) Named capturing group — capture with a label
a|b Alternation — matches a or b
\1 Backreference to group 1 (in pattern or replacement)
$1 or \1 Backreference in replacement string
// Reorder "last, first" → "first last"
"Smith, John".replace(/(\w+), (\w+)/, "$2 $1")
// → "John Smith"

// Named group
const m = "2026-07-13".match(/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/)
console.log(m.groups.year)  // "2026"

Lookahead and lookbehind

Zero-width assertions — test what comes before or after the current position without including it in the match.

Pattern Type Meaning
(?=...) Positive lookahead Followed by ...
(?!...) Negative lookahead NOT followed by ...
(?<=...) Positive lookbehind Preceded by ...
(?<!...) Negative lookbehind NOT preceded by ...
\d+(?= dollars)     matches digits only when followed by " dollars"
\d+(?! dollars)     matches digits NOT followed by " dollars"
(?<=\$)\d+          matches digits only when preceded by "$"
(?<!\$)\d+          matches digits NOT preceded by "$"

Lookbehind support is broad in modern runtimes (Node 8+, Python, Java, .NET, PHP PCRE) but was added to V8 (Chrome/Node) later — check your target environment for older browser support.

Flags / modifiers

Applied after the closing / in literal regex syntax.

Flag JS Python Go PHP Effect
Case-insensitive i re.I (?i) i A matches a
Multiline m re.M (?m) m ^/$ match line boundaries
Dotall s re.S (?s) s . matches newline too
Global (all matches) g (use findall) (use FindAll) g Find every match, not just first
Unicode u default default u Full Unicode property support
Verbose (extended) re.X (?x) x Allows whitespace and comments in pattern
// JS: case-insensitive, global
const matches = "Hello WORLD world".match(/world/gi)
// → ["WORLD", "world"]

Escape sequences

Sequence Matches
\. Literal dot (without escape, . means any char)
\* Literal asterisk
\+ Literal plus
\? Literal question mark
\( \) Literal parentheses
\[ \] Literal square brackets
\{ \} Literal curly braces
\\ Literal backslash
| Literal pipe
\^ Literal caret
\$ Literal dollar sign
\t Tab
\n Newline
\r Carriage return

Rule: Any regex special character (\ ^ $ . | ? * + ( ) [ ] { }) must be escaped with \ to match it literally.

Quick reference: language syntax

Task JavaScript Python Go PHP
Test if match /pat/.test(str) re.search(pat, str) regexp.MatchString(pat, str) preg_match($pat, $str)
Get first match str.match(/pat/) re.search(pat, str).group() re.FindString(str) preg_match($pat, $str, $m)
Get all matches str.match(/pat/g) re.findall(pat, str) re.FindAllString(str, -1) preg_match_all($pat, $str, $m)
Replace first str.replace(/pat/, rep) re.sub(pat, rep, str, count=1) re.ReplaceAllString(str, rep) preg_replace($pat, $rep, $str, 1)
Replace all str.replace(/pat/g, rep) re.sub(pat, rep, str) re.ReplaceAllString(str, rep) preg_replace($pat, $rep, $str)
Split str.split(/pat/) re.split(pat, str) re.Split(str, -1) preg_split($pat, $str)
Compile/cache new RegExp(pat, flags) re.compile(pat) regexp.MustCompile(pat) preg_match (auto-cached)

Ready-to-use patterns

Copy and adapt these validated patterns.

Email address (simple, practical)

^[\w.+-]+@[\w-]+\.[\w.]{2,}$

Matches user@example.com, user+tag@sub.domain.co. Not RFC 5321 complete — use a proper library for strict validation.

URL (http/https)

https?://[\w-]+(\.[\w-]+)+([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?

IPv4 address

^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$

Matches 192.168.1.1, rejects 999.0.0.1.

Date: YYYY-MM-DD (ISO 8601)

^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$

Structure-valid only — accepts 2026-02-31 (February 31). Use date parsing to validate calendar correctness.

Date: MM/DD/YYYY

^(0[1-9]|1[0-2])\/(0[1-9]|[12]\d|3[01])\/\d{4}$

Time: HH:MM or HH:MM:SS (24-hour)

^([01]\d|2[0-3]):[0-5]\d(:[0-5]\d)?$

Phone number (flexible, international)

^\+?[\d\s\-().]{7,15}$

For strict E.164: ^\+[1-9]\d{7,14}$.

Postal / ZIP code (US)

^\d{5}(-\d{4})?$

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}$

Hex color code

^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$

Matches #fff, #1a2b3c, #ff000080.

Slug (URL-friendly)

^[a-z0-9]+(?:-[a-z0-9]+)*$

Matches my-blog-post, rejects My Blog Post, --double-dash.

Credit card number (digits only, major networks)

^(?:4\d{12}(?:\d{3})?|5[1-5]\d{14}|3[47]\d{13}|6011\d{12})$

Visa, Mastercard, Amex, Discover — without spaces/dashes. Never store raw card numbers; use a payment processor.

Strong password (8+ chars, upper, lower, digit, special)

^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*]).{8,}$

Whitespace-only line (for cleanup)

^\s*$

HTML tag (simple strip — not for full HTML parsing)

<[^>]+>

6 common regex mistakes

1. Forgetting to escape special characters. The pattern 3.14 matches "3x14" because . means any character. Use 3\.14 to match a literal dot.

2. Using greedy quantifiers when lazy is needed. <.+> on <b>bold</b> matches the entire string, not each tag. Use <.+?> or <[^>]+> instead.

3. Not anchoring validation patterns. The pattern \d{4} matches any string containing 4 digits — including "abc1234xyz". Use ^\d{4}$ to match strings that are only 4 digits.

4. Catastrophic backtracking. Patterns like (a+)+ on a long non-matching string can run for seconds or minutes. Keep alternation outside repeated groups, avoid nested quantifiers on the same character class.

5. Mixing up match() return value in JavaScript. Without the g flag, str.match(/pat/) returns an array where index 0 is the full match and index 1+ are capture groups. With g, it returns all full matches but drops capture groups. Use str.matchAll(/pat/g) for all matches with capture groups.

6. Using regex for structured formats. Regex cannot validate balanced brackets, matching HTML tags, or correct calendar dates. Use a parser or date library for those cases; regex is for pattern shape, not semantic correctness.

6 FAQ

Can I use regex to parse HTML? For simple extraction of known, predictable patterns — yes. For parsing arbitrary HTML, use a DOM parser (DOMParser in JS, BeautifulSoup in Python, html.parser in Go/PHP). HTML is not a regular language and nested tags break naive regex.

What's the difference between match() and search() in Python? re.match() only matches at the start of the string. re.search() scans the entire string. Almost always use re.search() unless you specifically need start-of-string matching.

How do I match a newline with .? By default . does not match \n. Enable dotall mode: re.S in Python, (?s) inline flag in Go/PHP, the s flag in JavaScript (/pat/s). Alternatively, use [\s\S] which matches any character including newlines and works everywhere.

What is re.compile() for in Python? It pre-compiles the pattern into a regex object, which is slightly faster if you use the same pattern many times in a loop. For one-off matches, bare re.search(pattern, string) is fine.

How do I match Unicode characters? In JavaScript, add the u flag: /\p{L}+/u matches any Unicode letter. Python's re module handles Unicode in strings by default; use \p{...} via the regex library for full Unicode property support. In Go, regexp natively handles UTF-8.

How can I test my regex interactively? Use a free online regex tester to write your pattern, see matches highlighted in real time, and inspect capture groups — no setup required.

Related tools

Keep reading

All Toolmingotools are free & run in your browser

No sign-up, no upload, no watermark. Your files never leave your device.

Browse all tools