Table of Contents
- What Is a Regular Expression?
- Literal Characters — The Simplest Pattern
- Character Classes — Matching a Set of Characters
- Quantifiers — How Many Times?
- Anchors — Where in the String?
- The Wildcard — Matching Anything
- Escaping Special Characters
- Groups and Capturing
- Alternation — This or That
- Lookahead and Lookbehind
- Common Real-World Patterns
- Next Steps
1. What Is a Regular Expression?
A regular expression (regex) is a sequence of characters that defines a search pattern. Think of it as a miniature programming language for finding, extracting, and manipulating text.
Every developer encounters regex sooner or later — whether you're validating an email address, extracting data from a log file, finding all phone numbers in a document, or replacing text across thousands of files. Regex is one of those skills that pays for itself a hundred times over.
What Can You Do With Regex?
- Validate — Is this email address format valid? Is this phone number real?
- Search — Find all URLs, dates, or IP addresses in a document.
- Extract — Pull the username from an email, the error code from a log line.
- Replace — Change date formats, mask credit card numbers, clean up data.
- Split — Break a string into parts by a pattern rather than a fixed character.
2. Literal Characters — The Simplest Pattern
The most basic regex is a literal character. The pattern cat matches the letters c, a, t in that exact order. It's like a search function — but regex is anywhere in the string by default.
| Pattern | Matches | Does Not Match |
|---|---|---|
cat | cat, copycat, catalyst | dog, car, ct |
hello | hello, hello world | hell, hallo, he110 |
123 | 123, abc123 | 12, 1234 |
hello in the pattern field and hello world, hello there! in the test string. Notice how it finds both occurrences.
Literal characters are case-sensitive by default. Cat does not match cat. Most regex engines let you enable a case-insensitive flag (usually i).
3. Character Classes — Matching a Set of Characters
Sometimes you want to match any one of several characters. Character classes let you do that using square brackets [...].
| Pattern | Meaning | Matches |
|---|---|---|
[aeiou] | Any vowel | apple, octopus |
[0-9] | Any digit (same as \d) | Page 5, room 101 |
[a-z] | Any lowercase letter | hello |
[a-zA-Z] | Any letter (upper or lower) | Hello |
[^0-9] | Any character that is NOT a digit | a1b2c3 |
Shorthand Character Classes
Because character classes are so common, regex has shorthand versions:
| Shorthand | Equivalent | Meaning |
|---|---|---|
\d | [0-9] | Any digit |
\w | [a-zA-Z0-9_] | Any word character (letter, digit, underscore) |
\s | [ \t\n\r\f] | Any whitespace (space, tab, newline) |
\D | [^0-9] | Any non-digit |
\W | [^a-zA-Z0-9_] | Any non-word character |
\S | [^ \t\n\r\f] | Any non-whitespace |
# Example: Find all prices in a text
Pattern: \d+\.\d{2}
Text: "Apples cost 2.99, bananas 1.49, oranges 3.00"
Matches: 2.99, 1.49, 3.00
\d is shorter than [0-9], but [0-9] is clearer when you're teaching someone. Use the shorthand when you're comfortable.
4. Quantifiers — How Many Times?
Quantifiers tell regex how many times a character or group should appear. They come after the thing they apply to.
| Quantifier | Meaning | Example | Matches |
|---|---|---|---|
* | Zero or more | ab*c | ac, abc, abbc, abbbc |
+ | One or more | ab+c | abc, abbc (not ac) |
? | Zero or one (optional) | ab?c | ac, abc (not abbc) |
{3} | Exactly 3 | \d{3} | 123, 456 in 12345 |
{2,4} | Between 2 and 4 | \d{2,4} | 12, 123, 1234 |
{2,} | 2 or more | \d{2,} | 12, 123, 12345 |
Greedy vs. Lazy Matching
By default, quantifiers are greedy — they match as much as possible. Adding a ? after the quantifier makes it lazy — it matches as little as possible.
Text: <div>Hello</div><div>World</div> Pattern: <.+> (greedy — matches the whole string) Pattern: <.+?> (lazy — matches each tag individually) Match 1: <div> (lazy finds each one) Match 2: </div> Match 3: <div> Match 4: </div>
+ means "at least one", * means "any number (including zero)", ? means "optional". When in doubt, test both greedy and lazy.
5. Anchors — Where in the String?
Anchors don't match characters — they match positions in the string.
| Anchor | Meaning | Example |
|---|---|---|
^ | Start of string | ^hello matches hello world but not say hello |
$ | End of string | world$ matches hello world but not world peace |
\b | Word boundary | \bcat\b matches cat but not catalog or copycat |
\B | Non-word boundary | \Bcat matches copycat but not cat |
When to Use Anchors
Anchors are essential for validation. Without them, a pattern like \d{5} will match any five-digit sequence anywhere — including inside a ten-digit number. With anchors, ^\d{5}$ ensures the entire string is exactly five digits.
# Without anchors — matches anywhere
Pattern: \d{5}
Text: "zip 90210 code"
Match: 90210 — but also finds 5 digits inside longer numbers
# With anchors — matches only whole string
Pattern: ^\d{5}$
Text: "90210"
Match: 90210
Text: "90210-1234"
Match: No match (because the string has more than 5 chars)
^...$ when validating a complete field like an email, phone number, or ZIP code. Skip anchors when you're searching for a pattern inside a larger text.
6. The Wildcard — Matching Anything
The dot . matches any single character except a newline. It's regex's wildcard.
| Pattern | Matches |
|---|---|
c.t | cat, cot, cut, c.t, c0t |
h.t | hat, hot, hit, hut |
... | Any three characters: abc, 123, a b |
Combined with quantifiers, the dot is extremely powerful — and dangerous:
Pattern: .* — matches everything (entire string)
Pattern: .+ — matches everything except empty strings
Pattern: .{3,} — matches any string of 3+ characters
.* is the most common source of regex bugs. It matches everything, including characters you didn't intend. Always prefer more specific patterns when possible:
- Instead of
.*, use\w*or[a-z]*if you know what you're looking for - Instead of
.+, use\d+for digits - Use lazy quantifiers (
.*?) when you want the smallest match
7. Escaping Special Characters
What if you want to match a literal dot, asterisk, or dollar sign? Since these characters have special meaning in regex, you need to escape them with a backslash \.
| To Match | Write | Example |
|---|---|---|
| A literal dot | \. | example\.com matches example.com (but not exampleXcom) |
| A literal asterisk | \* | 4\*4 matches 4*4 |
| A literal dollar sign | \$ | \$\d+ matches $19, $99 |
| A literal backslash | \\\\ | C:\\\\Users matches C:\Users |
| A literal plus | \+ | \+1 matches +1 in phone numbers |
Special characters that need escaping when you want them literally: \. ^ $ * + ? { } [ ] \ | ( )
\..
8. Groups and Capturing
Parentheses (...) serve two purposes in regex: they group parts of a pattern together, and they capture the matched text for later use.
Capturing Groups
Pattern: (\w+)@(\w+)\.(\w+) Text: "[email protected]" Group 1: user Group 2: example Group 3: com
Each pair of parentheses creates a capture group. You can reference these groups by number: $1, $2, etc. This is incredibly useful for replacements.
# Replace: Swap first and last name Pattern: (\w+), (\w+) Replace: $2 $1 Text: "Doe, John" Result: "John Doe"
Non-Capturing Groups
Sometimes you need to group but don't want to capture. Use (?:...) instead:
Pattern: (?:Mr|Mrs|Ms)\.?\s(\w+) Text: "Mr. Smith" and "Mrs Jones" Group 1: Smith, Jones (only the name is captured, not the title)
Backreferences
Inside the same pattern, \1, \2 refer back to previously captured groups. This is useful for finding repeated words or matching paired HTML tags:
# Find repeated words Pattern: (\w+) \1 Text: "the the" Match: the the # Match opening and closing HTML tags Pattern: <(\w+)>.*?\1> Text: "<b>bold</b> and <i>italic</i>" Matches: <b>bold</b>, <i>italic</i>
9. Alternation — This or That
The pipe | acts like an OR operator. It matches the pattern on either side.
Pattern: cat|dog Text: "I have a cat and a dog" Matches: cat, dog
Alternation is often combined with groups to limit the scope:
Pattern: (apple|banana) pie Text: "apple pie is better than banana pie" Matches: apple pie, banana pie # Without parentheses, the pipe applies to the whole pattern Pattern: apple|banana pie Text: "apple pie" Match: apple (just "apple", not "apple pie")
apple|banana pie means apple OR banana pie, not apple pie OR banana pie.
10. Lookahead and Lookbehind
Lookaheads and lookbehinds are zero-width assertions — they check if a pattern can be matched without including it in the result. Think of them as "peek ahead" or "peek behind" without consuming characters.
Lookahead (?=...)
Matches if the pattern inside follows the current position, but doesn't include it:
Pattern: \d+(?= dollars) Text: "50 dollars, 30 euros" Matches: 50 (only "50", not "dollars")
Negative Lookahead (?!...)
Matches if the pattern inside does not follow:
Pattern: \d+(?! dollars) Text: "50 dollars, 30 euros" Matches: 30 (only "30", not "euros")
Lookbehind (?<=...)
Matches if the pattern inside precedes the current position:
Pattern: (?<=\$)\d+ Text: "Price: $50, Cost: 30" Matches: 50 (only the number after $)
Negative Lookbehind (?
Matches if the pattern inside does not precede:
Pattern: (?Practical use: Lookarounds are perfect for extracting values without including the surrounding context. For example, extracting prices:(?<=\$)\d+\.?\d*finds all dollar amounts and returns just the number.
11. Common Real-World Patterns
Here are patterns you'll actually use. Copy them, test them, modify them:
| Purpose | Pattern |
|---|---|
| Email address | ^[\w.-]+@[\w.-]+\.\w{2,}$ |
| URL | https?://[\w./?-]+ |
| US phone number | \(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4} |
| IP address (IPv4) | \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b |
| Date (YYYY-MM-DD) | \d{4}-\d{2}-\d{2} |
| Time (HH:MM) | \b\d{2}:\d{2}\b |
| Hexadecimal color | #[0-9a-fA-F]{6} |
| Username (3-16 chars, alphanumeric) | ^[a-zA-Z0-9_]{3,16}$ |
| File path | [\w./-]+\.\w+ |
| Whitespace trim | ^\s+|\s+$ |
12. Next Steps
You now know enough regex to handle 80% of real-world tasks. Here's what to do next:
- Practice. Open the Regex Tester and experiment. Try finding patterns in your own text.
- Bookmark the Cheat Sheet. It's your reference when you forget a syntax.
- Start small. Use regex for simple tasks first: find all numbers, extract URLs, validate formats.
- Build up. Combine what you've learned. A validation pattern often uses anchors, character classes, quantifiers, and groups together.
- Test edge cases. Empty strings, very long strings, strings with special characters — regex behavior can surprise you.