Regex Cheat Sheet: Patterns You'll Actually Use
Table of Contents
Regular expressions are the closest thing programming has to a spell you memorize once and cast forever. And yet most developers treat them like a haunted attic: they copy a pattern from the internet, it mostly works, and they never open it again because the last time they tried to write one from scratch they lost forty minutes to a misplaced parenthesis.
Here's the thing nobody tells you: you don't need to master regex. You need about a dozen patterns and a genuine understanding of three ideas — greediness, character classes, and anchors. That covers roughly 95% of what working developers actually do with regex: validating input, extracting pieces from text, and finding-and-replacing with structure. This guide is that 95%, with every pattern broken down in plain English so you can modify it instead of fearing it.
The Two-Minute Foundation: Anchors and Character Classes
Before the patterns, the foundation — because every mistake in this guide traces back to skipping it.
Anchors say where in the string the match must happen. `^` means "start of the string" and `$` means "end of the string." Without them, your pattern matches anywhere — so a phone-number pattern without anchors will happily match inside a longer string of garbage. The number-one regex validation bug in the wild is a missing `^...$` pair: the pattern is correct but it validates substrings instead of the whole input. If your validation "works in testing" but accepts nonsense in production, check your anchors first.
Character classes say what kind of character is allowed at one position. `\d` means any digit, `\w` means word characters (letters, digits, underscore), `\s` means whitespace, and `.` means any character at all (except newlines, usually). Square brackets define your own set: `[aeiou]` matches one vowel, `[0-9]` matches one digit, `[^0-9]` with the caret means "anything except a digit." Quantifiers say how many: `*` means zero or more, `+` means one or more, `?` means zero or one, and `{2,4}` means between two and four.
That's the whole foundation. Everything below is just these pieces combined.
Mistake 1: Greedy Matching Eats Your Whole Line
This is the mistake that makes beginners conclude regex is broken. Say you want to grab the content of the first HTML tag in `<b>hello</b> and <b>world</b>`. You write `<b>(.*)</b>`, expecting to capture `hello`. Instead you get `hello</b> and <b>world`. What happened?
The `.` is greedy: it grabs as much as it possibly can while still letting the overall pattern match. So it swallows everything up to the last `</b>` in the string, not the first. The fix is one character: make it lazy with `<b>(.?)</b>`. The `?` after a quantifier flips it to match as little as possible, so it stops at the first closing tag.
Greedy is the default because it's usually what you want when matching within known boundaries — but whenever you're extracting "the first X up to the next Y," reach for the lazy `*?` or `+?`. If your extraction keeps returning way more text than expected, greediness is guilty until proven innocent.
Mistake 2: The Unescaped Dot
The dot `.` means "any character," which makes it the most dangerous single character in a pattern. A pattern meant to match a filename like `report.pdf` — written as `report.pdf` — also matches `reportXpdf`, because the dot happily stands in for the `X`. In validation contexts this means your "must contain a dot" check accepts strings with no dot at all.
The fix is escaping: `\.` means a literal period. So `report\.pdf` matches only the actual filename. This bites hardest in two places: matching decimal numbers (`\d+\.\d+`, not `\d+.\d+`) and matching domain names or IP addresses, where every dot must be escaped. When a pattern matches things it shouldn't, look at every unescaped dot first.
The Patterns You'll Actually Copy
Here are the workhorses, each with a plain-English reading so you can adapt them. Test any of them live in the Regular Expression (RegEx) Live Tester — paste the pattern, paste your test strings, and watch the highlights update as you type.
Email: `^[^\s@]+@[^\s@]+\.[^\s@]+$` — reads as: "one or more characters that aren't whitespace or @, then a literal @, then one or more non-whitespace non-@ characters, then a literal dot, then one or more of the same." It won't catch every exotic valid email (the true RFC spec is absurd), but it rejects the garbage that actually shows up in forms: missing @, missing domain, spaces. Honestly, for real email validation, this regex plus sending a confirmation email beats any "perfect" pattern.
Phone (flexible international): `^\+?[\d\s\-().]{7,20}$` — "optional leading +, then 7 to 20 characters chosen from digits, spaces, dashes, dots, and parentheses." This validates shape, not any country's real numbering plan — and that's the right call. Strict per-country phone regexes break the moment a user formats their number differently. Validate the shape, then verify with an SMS code.
URL: `^https?:\/\/[^\s/$.?#].[^\s]*$` — "http with optional s, then ://, then a domain-ish chunk with no spaces, then anything without spaces." Good enough for form validation. Don't try to fully validate URLs with regex — parse them with your language's URL library instead and check the scheme and host programmatically.
Date (YYYY-MM-DD): `^\d{4}-\d{2}-\d{2}$` — four digits, dash, two digits, dash, two digits. Note what it doesn't do: it accepts `2026-99-99`. Regex validates shape; range validation (is month ≤ 12?) belongs in code. Trying to encode calendar logic into a pattern produces a monster nobody can maintain.
Slug: `^[a-z0-9]+(?:-[a-z0-9]+)*$` — lowercase letters and digits in groups joined by single dashes. Clean, and it rejects leading/trailing dashes and double dashes automatically.
Hex color: `^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$` — a # followed by exactly 3 or exactly 6 hex digits. The `(?:...)` is a non-capturing group — it groups without creating a capture, which keeps your match groups clean.
Capturing Groups: Extracting, Not Just Matching
So far we've validated — asking "does this string match?" But regex's real power is extraction: pulling structured pieces out of messy text. That's what capturing groups (plain parentheses) do.
Take a log line like `2026-10-08 14:32:11 ERROR Connection timeout after 30s`. The pattern `^(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2}) (\w+) (.*)$` captures four groups: date, time, level, message. Now you can reformat, filter, or route each piece independently. Groups are numbered left to right by their opening parenthesis, and most languages let you name them too — `(?<level>\w+)` in many flavors — which makes the extraction self-documenting.
Two group-related habits worth building: use non-capturing groups `(?:...)` when you need grouping but don't need the value (it keeps group numbering predictable), and remember that `|` alternation applies to the whole group it's in — `^cat|dog$` means "(starts with cat) or (ends with dog)," which is almost never what you want; `^(cat|dog)$` is.
Flags: The Three Modifiers That Change Everything
Case-insensitive (`i`): `[A-Z]` with the `i` flag also matches lowercase. Use it instead of writing both cases in your classes — `[a-zA-Z]` is just `[a-z]` with `i`.
Multiline (`m`): changes `^` and `$` to match at line boundaries instead of string boundaries. Essential when you're validating or extracting line-by-line within a bigger document. Without it, `^ERROR` only matches if the entire string starts with ERROR.
Global (`g`): find all matches, not just the first. In JavaScript, `"a1b2c3".match(/\d/)` returns `["1"]`; with the `g` flag it returns `["1","2","3"]`. Forgetting `g` when extracting multiple occurrences is a quiet bug — your code works, it just silently processes only the first match.
Try it free — no sign-up
Run the numbers yourself in seconds. Everything happens in your browser.
Open the Regular Expression (RegEx) Live TesterFrequently Asked Questions
Why does my regex match part of the string instead of the whole thing?
Because you didn't anchor it. A pattern like `\d{5}` matches any five consecutive digits anywhere in the input, including inside a ten-digit string. Wrap it: `^\d{5}$`. This is the single most common regex validation bug — the pattern is right, but it's validating a substring.
What is the difference between greedy and lazy matching?
Greedy quantifiers (`.`, `.+`) match as much text as possible while still allowing the overall pattern to succeed; lazy ones (`.?`, `.+?`) match as little as possible. Use greedy when consuming within known boundaries, lazy when extracting "up to the next occurrence" of something — like the content of the first HTML tag in a string with many.
How do I validate an email address with regex?
Use a pragmatic pattern like `^[^\s@]+@[^\s@]+\.[^\s@]+$` to reject obvious garbage, then send a confirmation email for real verification. A regex that perfectly implements the email RFC is thousands of characters long and still can't tell you whether the address actually exists — shape-check with regex, verify with a real email.
Why isn't my dot matching a literal dot?
Because `.` means "any character" in regex. Escape it as `\.` whenever you mean an actual period — in filenames, decimals, domain names, and IP addresses. Unescaped dots are the most common reason a pattern matches strings it shouldn't.
What are non-capturing groups and when should I use them?
`(?:...)` groups a sub-pattern without creating a numbered capture — useful for applying quantifiers or alternation to several tokens when you don't need the matched text afterward. They keep your capture numbering clean and signal to the next reader which groups carry meaningful data.
Is it safe to test regex patterns in an online tester?
For ordinary patterns and sample text, yes — and a live tester like the Regular Expression (RegEx) Live Tester is the fastest way to learn, since you see matches highlight as you type. Just don't paste production secrets or real user data into any web tool. Because Toolenix testers run entirely in your browser, your test strings never leave your machine, but the habit of keeping sensitive data local is worth building anyway.