Regex Cheat Sheet: 25 Patterns You'll Actually Use
A regular expression (regex) is a compact pattern that describes a set of strings — emails, dates, phone numbers, anything with a shape. Learn a handful of symbols and you can validate forms, pull data out of logs and rewrite text with one line. Below: the 25 patterns people reach for most, the core syntax behind them, and a worked example you can test right now in the free regex tester.
What is a regular expression?
A regular expression is a sequence of characters that defines a search pattern. Some characters match themselves (cat matches the text "cat"); others are metacharacters with special powers. \d matches any digit, + means "one or more of the previous thing", and ^ and $ anchor the match to the start and end of the string. Combine them and ^\d+$ means "the entire string is digits" — a one-line integer check.
The engine reads your pattern left to right and tries to match it against the text. When it finds a match it reports the matched substring (and any capture groups in parentheses). Everything below builds on this: the patterns are copy-paste ready, and the syntax table explains every symbol they use.
The 25 patterns
Each pattern is written for the common case. Anchors (^ $) are included where the pattern is meant to validate a whole field; leave them off when you want to find the pattern inside longer text. Try every pattern live in the regex tester — paste the pattern, paste sample text, and watch the highlights.
| # | What it matches | Pattern | Example match |
|---|---|---|---|
| 1 | Email address | [a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,} | [email protected] |
| 2 | URL (http/https) | https?://[^\s/$.?#].[^\s]* | https://example.com/docs?a=1 |
| 3 | IPv4 address | (?:\d{1,3}\.){3}\d{1,3} | 192.168.0.1 |
| 4 | Date YYYY-MM-DD | \d{4}-\d{2}-\d{2} | 2026-10-20 |
| 5 | Time HH:MM (24-hour) | ([01]\d|2[0-3]):[0-5]\d | 23:59 |
| 6 | US phone number | \(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4} | (415) 555-0132 |
| 7 | US ZIP code | \d{5}(-\d{4})? | 94107-1234 |
| 8 | Strong password (8+, upper, lower, digit, symbol) | ^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$ | Tr7$kq!mP |
| 9 | Hex color (#rgb or #rrggbb) | #[0-9a-fA-F]{6}\b|#[0-9a-fA-F]{3}\b | #1a2B3c |
| 10 | Username (3–16, letters/digits/_) | ^[a-zA-Z0-9_]{3,16}$ | dev_anna42 |
| 11 | URL slug (lowercase, hyphens) | ^[a-z0-9]+(?:-[a-z0-9]+)*$ | regex-cheat-sheet |
| 12 | Integer (optional sign) | ^[+-]?\d+$ | -42 |
| 13 | Decimal number | ^-?\d+(\.\d+)?$ | 3.14159 |
| 14 | Double-quoted string (handles escapes) | "([^"\\]|\\.)*" | "say \"hi\"" |
| 15 | HTML tag | <[^>]+> | <a href="x"> |
| 16 | Leading/trailing whitespace | ^\s+|\s+$ | " padded " |
| 17 | Repeated word | \b(\w+)\s+\1\b | the the |
| 18 | Credit card (16 digits, optional separators) | \d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4} | 4111 1111 1111 1111 |
| 19 | Filename with extension | ^[^\\/:*?"<>|\r\n]+\.[a-zA-Z0-9]{1,5}$ | report-final.pdf |
| 20 | Markdown heading | ^#{1,6}\s+.*$ | ## Worked example |
| 21 | Extract domain from email | @([\w.-]+\.\w+) | @mail.co.uk → mail.co.uk |
| 22 | URL query value (utm_source) | [?&]utm_source=([^&]*) | ?utm_source=news → news |
| 23 | Trailing spaces at line end | [ \t]+$ | "code " |
| 24 | Character repeated 3+ times | (.)\1{2,} | soooo |
| 25 | camelCase word boundary | (?<=[a-z])(?=[A-Z]) | cheat|Sheet (split point) |
A few honest caveats. Pattern 3 accepts 999.999.999.999 — it checks shape, not the 0–255 range (true validation needs a much longer pattern). Pattern 8 checks character classes, not real strength; "Password1!" passes it and is still a terrible password. Pattern 18 checks the digit shape, not the Luhn checksum. Regex is a first filter, not a proof.
The core syntax behind the patterns
You don't need to memorize the table above — you need this one. Nearly every pattern is built from these pieces:
| Symbol | Meaning | Example |
|---|---|---|
^ $ | Start / end of string (or line, with multiline flag) | ^cat$ matches only "cat" |
. | Any single character except newline | c.t matches cat, cut, c8t |
\d \w \s | Digit / word char (letter, digit, _) / whitespace | \d\d:\d\d matches 09:30 |
\D \W \S | The opposites: non-digit, non-word, non-whitespace | \S+@\S+ rough email |
[abc] [^abc] | One of these / anything but these | [aeiou] one vowel |
[a-z] [0-9] | Character ranges | [A-Z][a-z]+ capitalized word |
* + ? | Zero or more / one or more / zero or one | ab*c matches ac, abc, abbc |
{n} {n,} {n,m} | Exact / at least n / between n and m repetitions | \d{4}-\d{2}-\d{2} a date |
( ) (?: ) | Capture group / non-capturing group | (\w+)@ captures the name |
\1 \2 | Backreference to group 1, 2… | (\w+)\s+\1 repeated word |
| | Alternation (or) | cat|dog either word |
\b | Word boundary | \bcat\b not "cats" or "concat" |
(?=…) (?!…) | Lookahead / negative lookahead (zero-width) | foo(?=bar) foo only before bar |
(?<=…) (?<!…) | Lookbehind / negative lookbehind (zero-width) | (?<=\$)\d+ digits after $ |
\ | Escape: literal next character | \. a real dot, \\ a backslash |
Worked example: validating a batch of emails
Say you collected six addresses from a signup form and want to check them with pattern 1 ([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}) before importing them:
| Address | Verdict | Why |
|---|---|---|
| [email protected] | ✓ valid | name, @, domain, dot, 3-letter TLD |
| [email protected] | ✓ valid | dots, plus-tag and multi-part domain are all allowed |
| [email protected] | ✓ valid | underscore and subdomain pass |
| plainaddress | ✗ rejected | no @ sign at all |
| @nodomain.com | ✗ rejected | empty local part — the + requires at least one character |
| user@domain | ✗ rejected | no dot + TLD, which the pattern requires |
Result: 3 of 6 pass, 3 are caught — and each rejection names the exact defect. Notice the walkthrough: the engine tries the pattern at each position, the [...]+ chunks greedily consume as much as they can, and the @ and \. act as fixed landmarks that must be present. When a landmark is missing, the whole match fails fast. That "landmarks plus flexible chunks" shape is the template for most validation patterns — phone numbers, dates and ZIP codes all work the same way.
Practical tips
- Anchor validations, don't anchor searches. Use
^…$when the whole field must match (a form input); drop the anchors when extracting from longer text, or a valid email buried in a paragraph will never be found. - Escape the dot in domains.
example.commatches "exampleXcom" too. The most common regex bug in the wild is an unescaped dot — writeexample\.com. - Prefer
+over*for required parts.\d*matches an empty string, which lets "nothing" count as a number. If the part must exist,+says so. - Use non-capturing groups by default.
(?:…)groups without creating a numbered capture, keeping\1,\2predictable and the match result clean. Reserve(…)for parts you actually want to extract. - Test with hostile input. Empty strings, unicode, 10,000-character lines, and the classic "
a@b" for email patterns. Paste the nastiest cases into the regex tester before shipping — edge cases are where patterns break. - Know when not to use regex. Nested structures (full HTML, JSON, balanced parentheses) are beyond what regular expressions handle well. Pattern 15 finds tags; it cannot parse a document. Reach for a real parser there.
Try it yourself
Paste any pattern from this cheat sheet and test it against your own text — matches highlight instantly, all in your browser.
Frequently asked questions
What is regex used for?
Regular expressions validate input (emails, phone numbers, passwords), extract pieces of text from logs and documents, and power find-and-replace in code editors and scripts. If you have ever checked that a form field looks like an email address, pulled all the links out of a web page, or renamed a hundred files with one command, you have used a regex job. They appear in nearly every programming language and in tools like VS Code, grep and Google Sheets.
Why is my regex not matching?
The usual suspects: a special character that needs escaping (a bare . matches any character, not a literal dot), a greedy quantifier eating more than intended, missing anchors so the match succeeds in the wrong place (or failing because anchors require a full match), and flags — a pattern that needs multiline or case-insensitive mode will silently fail without them. Paste the pattern and a failing sample into a tester and read the match highlight; the failure is almost always visible in one glance.
What is the difference between * and +?
The * quantifier means zero or more of the preceding element, while + means one or more. So colou*r matches both color and colour, but colou+r requires the u to appear at least once and matches only colour. A practical consequence: \d* can match an empty string, which surprises people when a pattern matches at a position where there are no digits at all. Use + when the thing must actually be there.
Do I need to escape the dot in regex?
Outside a character class, yes. A bare . is a wildcard that matches any single character (except newlines), so example.com as a pattern would also match exampleXcom. Write example\.com for a literal dot. Inside a character class, the dot loses its special meaning — [.] matches a literal dot with no backslash. The same rule applies to most metacharacters: inside [...], +, *, ?, ( and ) are plain characters.
What are lookahead and lookbehind in regex?
They are zero-width assertions: conditions that check what comes next (lookahead) or what came just before (lookbehind) without consuming any characters. The strong-password pattern (?=.*[A-Z]) is a lookahead — it requires an uppercase letter somewhere ahead while the overall match stays at the start of the string. Negative forms (?!...) and (?<!...) assert that something is absent. Because they add no characters to the match, you can stack several independent conditions at one position.
Is the email regex in this cheat sheet perfect?
No, and no short regex can be. The pattern here catches typos and malformed input — missing @, missing domain, illegal characters — which covers the realistic cases in forms and data cleaning. True email syntax is far stranger than most people expect (quoted local parts, IP domains), and a fully correct validator is hundreds of characters long and still can't prove the address exists. For real signup flows, pair a simple pattern like this one with a confirmation email; that is the only check that proves deliverability.