Regex Cheat Sheet for Beginners
Regular expressions look like line noise until the handful of building blocks click into place. There are fewer than you think. This page covers everything needed for the patterns you will actually write.
Character classes
| Pattern | Matches |
|---|---|
. | Any character except a newline |
\d | Any digit, 0–9 |
\D | Any non-digit |
\w | Word character: letter, digit, or underscore |
\W | Any non-word character |
\s | Whitespace: space, tab, newline |
\S | Any non-whitespace |
[abc] | Any one of a, b, or c |
[^abc] | Any character except a, b, or c |
[a-z] | Any lowercase letter |
[0-9a-fA-F] | Any hexadecimal digit |
The pattern is consistent: capitalising the letter negates it. \d is a digit, \D is anything but.
Quantifiers
| Pattern | Meaning |
|---|---|
* | Zero or more |
+ | One or more |
? | Zero or one — makes it optional |
{3} | Exactly three |
{2,} | Two or more |
{2,5} | Between two and five |
Anchors and boundaries
| Pattern | Meaning |
|---|---|
^ | Start of the string, or of a line with the m flag |
$ | End of the string, or of a line with the m flag |
\b | Word boundary — the edge between a word and a non-word character |
\B | Not a word boundary |
Word boundaries are more useful than beginners expect. Searching for cat matches inside "concatenate"; searching for \bcat\b matches only the standalone word.
Groups and alternation
(abc)— a capture group. The matched text can be reused as$1in a replacement.(?:abc)— groups without capturing. Slightly faster and keeps your group numbers tidy.(?<name>abc)— a named group, referenced as$<name>.cat|dog— alternation, matching either side.(?=abc)— positive lookahead: asserts what follows without consuming it.(?!abc)— negative lookahead: asserts what does not follow.
Flags
g— global. Find every match instead of stopping at the first.i— case insensitive.m— multiline. Makes^and$match at line boundaries.s— dotall. Lets.match newlines, which it otherwise will not.u— unicode. Needed for correct handling of emoji and non-Latin scripts.
The greedy matching trap
This catches everyone exactly once, and it is worth understanding properly.
Quantifiers are greedy by default — they take as much as possible, then give back only what they must. Against the text <b>one</b> and <b>two</b>, the pattern <b>.*</b> matches the entire string, not the first tag pair, because .* grabs everything and backtracks only far enough to find a final </b>.
Adding ? makes a quantifier lazy, taking as little as possible. <b>.*?</b> stops at the first closing tag and returns two matches. If your pattern is matching far more than intended, this is almost always why.
Patterns worth keeping
| Goal | Pattern |
|---|---|
| Email (practical) | [\w.%+-]+@[\w.-]+\.[A-Za-z]{2,} |
| URL | https?:\/\/[^\s]+ |
| ISO date | \d{4}-\d{2}-\d{2} |
| Hex colour | #[0-9a-fA-F]{3,6}\b |
| Leading/trailing space | ^\s+|\s+$ |
| Repeated whitespace | \s{2,} |
| HTML tag | <[^>]+> |
| Duplicated word | \b(\w+)\s+\1\b |
That last one uses a backreference: \1 means "the same text the first group matched", so it finds "the the" and "is is".
Two things regex should not do
Do not parse HTML with it. Regular expressions cannot handle arbitrary nesting, which is exactly what markup is. A pattern that works on your test input will break on real HTML with nested tags, attributes containing angle brackets, or comments. Use a parser. For simply stripping tags from text you control, the HTML stripper is the pragmatic option.
Do not try to fully validate email addresses. The specification-complete pattern runs to thousands of characters and still accepts addresses that do not exist. The practical pattern above is fine for extraction; the only real validation is sending a message. Our email extractor uses exactly that approach.
Test before you ship
Regex is written by iteration, not inspiration. Build the pattern piece by piece against real sample data in the regex tester, which highlights matches live and shows capture groups and positions as you type. Once it works, use it in the find and replace tool to apply it across a whole document.
And leave a comment above any non-trivial pattern explaining what it matches. Regex is famously write-only — the person who cannot read it in six months is usually you.