Regex Cheat Sheet: Tokens, Anchors & Quantifiers
A practical regex cheat sheet: character classes, anchors, quantifiers, groups, and the metacharacters you must escape, plus worked examples for real-world patterns.
The Regex Cheat Sheet: Tokens, Anchors, and Quantifiers Made Simple
This regex cheat sheet is a fast reference to the regular expression syntax you actually use: character classes, anchors, quantifiers, groups, and the metacharacters that need escaping. Regular expressions are tiny pattern-matching programs — a compact language for describing the shape of text so you can search, validate, extract, or replace it. Master a dozen symbols and you can match almost anything.
If you came here for a quick answer, the core is small: . matches any character, \d a digit, \w a word character, * means "zero or more," + means "one or more," ^ and $ anchor to the start and end of a line, and [...] defines a set of allowed characters. Everything else is a combination of these. The tables below give you the full reference, followed by worked examples and the gotchas that cause most regex bugs. To experiment as you read, paste any pattern into our free Regex Tester and watch matches highlight live.
How a Regular Expression Reads
A regex is scanned left to right against your input. Most characters match themselves literally — the pattern cat matches the letters c-a-t in that order. The power comes from metacharacters, which carry special meaning instead of matching literally. The engine tries to make the pattern fit the text, and by default it is "greedy," grabbing as much as it can while still allowing the overall pattern to succeed.
Understanding that one idea — literals plus metacharacters, matched greedily — explains nearly every surprising result you will hit. The cheat sheet that follows groups the metacharacters by job.
Character Classes and Shorthands
Character classes define which characters are allowed at a position. Shorthands are pre-built classes for the most common groups.
| Token | Matches | Example |
|---|---|---|
. | Any character except newline | a.c matches "abc", "a9c" |
\d | Any digit (0-9) | \d\d matches "42" |
\D | Any non-digit | \D matches "x" |
\w | Word character (letter, digit, underscore) | \w+ matches "user_1" |
\W | Non-word character | \W matches "@" |
\s | Whitespace (space, tab, newline) | \s matches " " |
\S | Non-whitespace | \S matches "k" |
[abc] | Any one of a, b, or c | [aeiou] matches a vowel |
[^abc] | Any character except a, b, c | [^0-9] matches a non-digit |
[a-z] | Any character in a range | [A-Fa-f] matches a hex letter |
The uppercase shorthands are always the negation of their lowercase versions: \d is a digit, \D is anything that is not a digit. Inside a class, a caret at the very start ([^...]) negates the whole set.
Anchors and Boundaries
Anchors match positions rather than characters. They have zero width — they assert "you are here" without consuming any text.
| Token | Asserts | Example |
|---|---|---|
^ | Start of string (or line in multiline mode) | ^Hello matches a line starting with Hello |
$ | End of string (or line) | end$ matches a line ending in "end" |
\b | Word boundary | \bcat\b matches "cat" but not "category" |
\B | Not a word boundary | \Bcat matches "cat" inside "scat" |
The word boundary \b is one of the most useful and most under-used tokens. It is what stops a search for cat from also matching "scatter" and "education."
Quantifiers
Quantifiers control how many times the preceding element may repeat. This is where most real-world patterns get their flexibility.
| Token | Meaning | Example |
|---|---|---|
* | Zero or more | ab* matches "a", "ab", "abbb" |
+ | One or more | ab+ matches "ab", "abbb" (not "a") |
? | Zero or one (optional) | colou?r matches "color" and "colour" |
{n} | Exactly n times | \d{4} matches a 4-digit year |
{n,} | n or more times | \d{2,} matches 2+ digits |
{n,m} | Between n and m times | \d{1,3} matches 1 to 3 digits |
*? +? | Lazy versions (match as few as possible) | <.*?> matches one tag, not a whole line |
By default quantifiers are greedy: .* grabs everything it can. Add a ? to make them lazy, so they grab as little as possible. The difference between greedy and lazy matching is the single biggest source of "why did my regex match too much?" confusion.
Groups and Alternation
Parentheses group part of a pattern so a quantifier can apply to the whole group, and they capture the matched text for reuse. The pipe is alternation — a logical OR.
| Token | Meaning | Example |
|---|---|---|
(...) | Capturing group | (ab)+ matches "abab" |
(?:...) | Non-capturing group | (?:https?) groups without capturing |
a|b | Match a OR b | cat|dog matches either word |
\1 | Backreference to group 1 | (\w)\1 matches a doubled letter |
Escaping: The Metacharacters You Must Escape
To match a metacharacter literally, escape it with a backslash. The characters that need escaping outside a character class are: . ^ $ * + ? ( ) [ ] { } | \ and the forward slash if it delimits your pattern. For example, to match a literal dot in a domain name you write \., and to match a dollar amount you write \$\d+.
Rule of thumb: if a symbol does something special in regex, put a backslash in front of it to match it literally.3\.14matches the string "3.14";3.14would also match "3x14".
Worked Examples
Patterns make sense fastest when you see them solve a real problem. Here are common tasks broken down.
Validate a Simple Email Shape
Pattern: ^[\w.+-]+@[\w-]+\.[\w.-]+$. Reading it left to right: anchor to the start, one or more word characters or . + - (the local part), a literal @, one or more word characters or hyphens (the domain), a literal dot, then the top-level domain, anchored to the end. This is a pragmatic shape-check, not a full RFC-compliant validator, but it catches the vast majority of typos.
Match a 24-Hour Time
Pattern: ^([01]\d|2[0-3]):[0-5]\d$. The hour is either 0 or 1 followed by any digit, or 2 followed by 0-3. Then a colon, then minutes from 00 to 59. This shows how alternation inside a group lets you express real-world constraints precisely.
Extract All Hashtags
Pattern: #\w+. The literal # followed by one or more word characters. Run globally over a caption and every hashtag is captured. Add a word boundary or anchor if you need to avoid matching mid-word symbols.
Greedy vs Lazy in Action
Given the text <b>bold</b>, the pattern <.*> greedily matches the entire string, because .* swallows everything up to the last >. The lazy pattern <.*?> matches only <b>. When you want the smallest possible match, reach for the lazy quantifier.
Flags That Change Everything
- g (global) — find all matches, not just the first. Essential for replace-all and extraction.
- i (case-insensitive) —
catalso matches "CAT" and "Cat". - m (multiline) — makes
^and$match at every line break, not just the string boundaries. - s (dotall) — lets
.match newline characters too.
Flags are set differently per language, but their meanings are consistent. The fastest way to learn how they interact is to toggle them on a live pattern in the Regex Tester and watch the highlighted matches change in real time.
Putting the Cheat Sheet to Work
The trick with regex is to build patterns incrementally. Start with the literal core, add a character class, then a quantifier, then anchors, testing after each addition. Trying to write the whole pattern in one shot is how you end up with something that almost works but matches three cases too many. Keep this cheat sheet open, test as you go, and explore more developer utilities in the Development Tools hub. If your work touches data formats and IDs, our guides on generating UUIDs in Python and the decimal to ASCII reference are handy companions.
Frequently Asked Questions
What is the difference between greedy and lazy quantifiers?
Greedy quantifiers like * and + match as much text as possible while still allowing the overall pattern to succeed. Lazy quantifiers, written by adding ? (such as *? or +?), match as little as possible. Use lazy quantifiers when you want the shortest match, such as a single HTML tag instead of a whole line.
When do I need to escape a character in regex?
Escape a character with a backslash whenever you want to match a metacharacter literally. The characters needing escaping are . ^ $ * + ? ( ) [ ] { } | \ and your delimiter slash. For example, \. matches a literal dot, while an unescaped . matches any character.
What does the word boundary \b do?
The \b token asserts a position between a word character and a non-word character. It lets you match whole words: \bcat\b matches "cat" as a standalone word but not "category" or "scatter". It matches a position, not an actual character.
What is the difference between a capturing and non-capturing group?
A capturing group (...) both groups a sub-pattern and stores its matched text for backreferences or extraction. A non-capturing group (?:...) only groups, without storing the match. Use non-capturing groups when you need grouping for a quantifier or alternation but do not need to reference the result.
Why does my regex match more text than expected?
Almost always because of greedy quantifiers. By default .* consumes everything it can. Either switch to a lazy quantifier (.*?) or use a more specific character class such as [^>]* so the match cannot overrun past the character you want to stop at.
Do regex flags work the same in every language?
The common flags (global, case-insensitive, multiline, dotall) mean the same thing across most engines, but the syntax for setting them and a few advanced features differ. JavaScript, Python, PCRE, and others share the core token set in this cheat sheet, so patterns are largely portable with minor adjustments.
What does \d{2,4} mean?
It matches between 2 and 4 digits. The {n,m} quantifier sets a minimum and maximum repeat count. So \d{2,4} matches "12", "123", or "1234" but not a single digit or five digits in a row.
How do I match either of two words?
Use alternation with the pipe: cat|dog matches "cat" or "dog". Wrap it in a group when combining with other tokens, for example (cat|dog)s? to optionally match a plural. Non-capturing groups (?:cat|dog) work too if you do not need to capture.