The Developer's Guide to Regular Expressions (Regex Made Simple)
A practical regex tutorial with real examples — learn regular expression syntax, character classes, groups, lookaheads, and how to use regex in JavaScript, Python, and more.
Get more content like this on Telegram!
Daily AI tips, notes & resources — free
The Developer's Guide to Regular Expressions (Regex Made Simple)
The first time I saw a regular expression in production code, I was convinced the original developer had fallen asleep on their keyboard.
const emailRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
I had no idea what that meant. I copied it without understanding it. Three months later I needed to modify it for a slightly different validation rule and spent two hours staring at random characters.
Regex has a reputation for being impenetrable. That reputation is partly deserved — regex can become very complex. But the 20% of regex syntax that covers 80% of practical use cases is actually quite learnable in a few hours.
In this guide, you'll learn regex from the ground up with real examples that explain what each character means — so you can read, write, and debug regular expressions yourself.
The Mental Model: Patterns, Not Programs
A regex is a pattern describing text. The engine tries to find that pattern in a string.
Pattern: cat
String: "I have a cat named Whiskers"
Match: "cat" at position 9
Simple patterns match literally. The power comes from special characters that describe types of characters, repetition, and position.
Part 1: Character Matching
Literal Characters
Most characters match themselves:
/hello/.test('hello world'); // true
/hello/.test('Hello world'); // false — case sensitive
The Dot: Match Any Character
. matches any single character except a newline:
/h.t/.test('hat'); // true — 'a' matches .
/h.t/.test('hot'); // true — 'o' matches .
/h.t/.test('ht'); // false — need one character between h and t
/h.t/.test('h t'); // true — space matches .
Character Classes: [ ]
Match one character from a set:
/[aeiou]/.test('cat'); // true — 'a' is a vowel
/[0-9]/.test('abc3'); // true — '3' matches
/[a-z]/.test('Hello'); // true — 'e', 'l', 'l', 'o' match
// Negated class: [^] means NOT these characters
/[^aeiou]/.test('rhythm'); // true — 'r' is not a vowel
Shorthand Classes
These built-in shortcuts are used constantly:
| Shorthand | Matches | Equivalent |
|---|---|---|
\d | Any digit | [0-9] |
\w | Word character | [a-zA-Z0-9_] |
\s | Whitespace | [ \t\n\r\f] |
\D | Non-digit | [^0-9] |
\W | Non-word | [^a-zA-Z0-9_] |
\S | Non-whitespace | [^ \t\n\r\f] |
/\d{3}-\d{4}/.test('555-1234'); // true — phone number pattern
/\w+/.test('hello_world'); // true
/\s+/.test(' '); // true — whitespace
Part 2: Quantifiers
Quantifiers specify how many times a character or group should match:
| Quantifier | Meaning |
|---|---|
* | 0 or more |
+ | 1 or more |
? | 0 or 1 (optional) |
{n} | Exactly n times |
{n,m} | Between n and m times |
{n,} | n or more times |
/\d+/.test('12345'); // true — one or more digits
/\d*/.test('abc'); // true — zero digits still matches
/\d{3}/.test('123'); // true — exactly 3 digits
/\d{2,4}/.test('12345'); // true — 2 to 4 digits (matches '1234')
// Phone number: optional country code + 10 digits
/^(\+\d{1,3}-)?\d{3}-\d{3}-\d{4}$/
// Matches: "555-867-5309" and "+1-555-867-5309"
Part 3: Anchors
Anchors match position, not characters:
| Anchor | Meaning |
|---|---|
^ | Start of string |
$ | End of string |
\b | Word boundary |
/^hello/.test('hello world'); // true — starts with hello
/^hello/.test('say hello'); // false — doesn't start with hello
/world$/.test('hello world'); // true — ends with world
// Without anchors — matches anywhere in string
/cat/.test('scat'); // true — 'cat' appears in 'scat'
// With anchors — must match entire string
/^cat$/.test('scat'); // false — 'scat' ≠ 'cat'
/^cat$/.test('cat'); // true
Part 4: Groups and Capturing
Parentheses ( ) create groups:
Capturing Groups
const dateRegex = /(\d{4})-(\d{2})-(\d{2})/;
const match = '2025-05-15'.match(dateRegex);
// match[0] = '2025-05-15' (full match)
// match[1] = '2025' (group 1)
// match[2] = '05' (group 2)
// match[3] = '15' (group 3)
Named Capturing Groups
Much more readable, especially for complex patterns:
const dateRegex = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const { groups } = '2025-05-15'.match(dateRegex);
// groups.year = '2025'
// groups.month = '05'
// groups.day = '15'
Non-Capturing Groups: (?:)
Groups things without capturing the match:
// Captures: matches "2025-05" but only captures the year and month parts
const regex = /(?:20)(\d{2})-(\d{2})/;
'2025-05'.match(regex);
// match[1] = '25' (not '2025' — '20' was grouped but not captured)
Part 5: Alternation and Lookaheads
Alternation: |
The OR operator in regex:
/cat|dog|bird/.test('I have a dog'); // true
/^(GET|POST|PUT|DELETE) \//.test('GET /api/users'); // true — HTTP methods
Lookaheads
Match a pattern only if followed (or not followed) by another pattern, without consuming characters:
// Positive lookahead: (?=)
// Match "foo" only if followed by "bar"
/foo(?=bar)/.test('foobar'); // true
/foo(?=bar)/.test('foobaz'); // false
// Negative lookahead: (?!)
// Match "foo" only if NOT followed by "bar"
/foo(?!bar)/.test('foobaz'); // true
/foo(?!bar)/.test('foobar'); // false
// Real use: match a price not followed by a % sign
// (to distinguish "$10" from "10%" in text)
/\$\d+(?!%)/.test('$10 off'); // true
/\$\d+(?!%)/.test('10%'); // false
Part 6: Flags
Flags modify how the regex engine operates:
| Flag | JavaScript | Meaning |
|---|---|---|
i | /pattern/i | Case insensitive |
g | /pattern/g | Global — find all matches |
m | /pattern/m | Multiline — ^ and $ match line starts/ends |
s | /pattern/s | Dot matches newlines too |
/hello/i.test('HELLO WORLD'); // true — case insensitive
// Find all email addresses in text
const text = 'Contact alice@example.com or bob@test.org';
const emails = text.match(/[\w.]+@[\w.]+\.\w+/g);
// ['alice@example.com', 'bob@test.org']
Practical Patterns You Can Use Today
// Email (simple — catches most typos)
const email = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
// URL
const url = /^https?:\/\/([\da-z.-]+)\.([a-z.]{2,6})([/\w .-]*)*\/?$/;
// Phone number (US)
const phone = /^\+?1?\s*\(?(\d{3})\)?[\s.-]?(\d{3})[\s.-]?(\d{4})$/;
// Password strength (min 8 chars, at least 1 upper, 1 lower, 1 digit)
const password = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$/;
// Date (YYYY-MM-DD)
const date = /^\d{4}-(0[1-9]|1[012])-(0[1-9]|[12]\d|3[01])$/;
// IPv4 address
const ipv4 = /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$/;
// Slug (URL-safe)
const slug = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
Test every regex at regex101.com before using in production — it explains what each part does and shows which parts of your test string match.
JavaScript Regex Quick Reference
const regex = /pattern/flags;
// Test if pattern exists
regex.test('string'); // true/false
// Find first match
'string'.match(/pattern/); // match object or null
// Find all matches
'string'.match(/pattern/g); // array or null
// Replace
'string'.replace(/old/, 'new'); // first occurrence
'string'.replace(/old/g, 'new'); // all occurrences
// Replace with function
'hello world'.replace(/\b\w/g, c => c.toUpperCase()); // 'Hello World'
// Split on pattern
'one,,two,three'.split(/,+/); // ['one', 'two', 'three']
// Extract with groups
const { groups } = '2025-05-15'.match(/(?<y>\d{4})-(?<m>\d{2})-(?<d>\d{2})/);
For applying regex in code quality tools, our VS Code extensions guide covers extensions that help you write and test regex inline.
Frequently Asked Questions
What is a regular expression and when should I use one?
A regex is a pattern used to match, search, or replace text. Use it for: validating formats, extracting data from text, find-and-replace with patterns. Don't use it where simple string methods (includes, startsWith) would work just as well.
Is regex the same in all programming languages?
Core syntax is similar across languages — \d, \w, *, +, ? are universal. Advanced features vary. Test your regex in the specific language/mode you'll use it in.
How do I test my regular expressions?
Use regex101.com (explains each token) or regexr.com. Test against at least 5 real examples including edge cases before using in production.
Why is my regex causing performance issues?
Catastrophic backtracking from nested quantifiers like (a+)+. Avoid nested repetitions and test your regex against inputs designed to trigger backtracking.
Should I use regex to validate email addresses?
A basic regex catches obvious typos. A perfect email regex is impossible per RFC 5322. Use a simple pattern for UI validation and email verification for actual confirmation.
Frequently Asked Questions
AiTechWorlds Team
✓ Verified WriterThe AiTechWorlds team is passionate about AI, technology, and education. We create high-quality, research-backed content to help you learn, grow, and succeed in the modern digital world.
Related Articles
15 Coding Habits That Separate Senior Developers from Juniors
Discover the coding habits senior developers follow every day — from writing readable code to debugging smarter — that separate pros from beginners.
The 10 VS Code Extensions That Make You Code Twice as Fast
The best VS Code extensions in 2025 that genuinely boost productivity — from AI code completion to live sharing, error highlighting, and formatting automation.
Terminal and Command Line Mastery: 30 Commands That Changed My Life
Learn essential terminal commands for developers — navigation, file operations, git, process management, and shell shortcuts that make you dramatically faster at the command line.
Data Structures for Humans: Finally Understanding Arrays, Trees, Graphs
Data structures explained simply for beginners — learn arrays, linked lists, stacks, queues, trees, and graphs with real-world analogies and practical code examples.