Character Classes
| Pattern | Matches | Example |
| . | Any character except newline | a.c → abc, aXc, a1c |
| \w | Word character: [a-zA-Z0-9_] | \w+ → hello, word_123 |
| \W | Non-word character | \W → space, !, @ |
| \d | Digit: [0-9] | \d{3} → 123, 456 |
| \D | Non-digit | \D+ → abc, hello |
| \s | Whitespace: space, tab, newline | \s+ → ' ', ' ' |
| \S | Non-whitespace | \S+ → any word |
| [abc] | Character set: a, b, or c | [aeiou] → vowels |
| [^abc] | Negated set: not a, b, or c | [^0-9] → non-digit |
| [a-z] | Range: a through z | [a-zA-Z] → any letter |
Quantifiers
| Pattern | Meaning | Example |
| * | 0 or more | ab* → a, ab, abb, abbb |
| + | 1 or more | ab+ → ab, abb, abbb (not a) |
| ? | 0 or 1 (optional) | colou?r → color, colour |
| {n} | Exactly n times | \d{4} → 2024 (exactly 4 digits) |
| {n,} | n or more times | \d{2,} → 12, 123, 1234 |
| {n,m} | Between n and m times | \d{2,4} → 12, 123, 1234 |
| *? | Lazy: as few as possible | <.*?> → in text |
| +? | Lazy 1+ | '.*?' → 'hello' in 'hello' 'world' |
Anchors & Boundaries
| Pattern | Meaning |
| ^ | Start of string (or line with m flag) |
| $ | End of string (or line with m flag) |
| \b | Word boundary (between \w and \W) |
| \B | Non-word boundary |
| \A | Start of string (Python/Java — not JS) |
| \Z | End of string (Python/Java) |
Groups & References
| Pattern | Meaning | Example |
| (abc) | Capture group | (\d{4}) captures year |
| (?:abc) | Non-capture group | (?:Mr|Mrs)\.? — group without capture |
| (?P...) | Named capture (Python) | (?P\d{4}) |
| (?...) | Named capture (JS/PCRE) | (?\d{4}) |
| \1, \2 | Backreference to group 1, 2 | (\w+) \1 matches 'the the' |
| (?=...) | Positive lookahead | \w+(?=\.com) |
| (?!...) | Negative lookahead | \d+(?! years) |
| (?<=...) | Positive lookbehind | (?<=\$)\d+ |
| (? | Negative lookbehind | (? |
Flags
| Flag | Meaning |
| g | Global: find all matches (not just first) |
| i | Case insensitive |
| m | Multiline: ^ and $ match start/end of each line |
| s | Dotall: . matches newline too |
| u | Unicode: enable Unicode matching |
| x | Extended: allow whitespace and comments (Python/Ruby) |
Common Validation Patterns
// Email address (practical, not RFC-perfect)
const email = /^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$/;
// URL (http or https)
const url = /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z]{2,6}([-a-zA-Z0-9@:%_+.~#?&/=]*)$/;
// Phone number (flexible international format)
const phone = /^\+?[\d\s\-().]{7,20}$/;
// US ZIP code
const zip = /^\d{5}(-\d{4})?$/;
// Date (YYYY-MM-DD)
const date = /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/;
// Hex color
const hexColor = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/;
// IPv4 address
const ipv4 = /^(\d{1,3}\.){3}\d{1,3}$/;
// Strong password (8+ chars, upper, lower, digit, special)
const password = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/;
// Slug (URL-friendly string)
const slug = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
// Credit card (Luhn check still needed separately)
const creditCard = /^\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}$/;
Common Regex Mistakes
- Catastrophic backtracking — nested quantifiers like
(a+)+ can cause exponential backtracking. Test with long strings and worst-case inputs before deploying.
- Not anchoring validation patterns —
/\d+/ matches any string containing a digit, including 'abc123xyz'. Use /^\d+$/ for full-string validation.
- Using regex for HTML parsing — regex cannot correctly parse HTML (nested tags, attributes with quotes). Use a proper HTML parser (DOM, BeautifulSoup, Cheerio).
- Forgetting to escape special characters — . * + ? ^ $ { } [ ] | ( ) \ are special in regex. To match them literally, escape with \.
- Case sensitivity — regex is case-sensitive by default. Add the
i flag for case-insensitive matching.
Frequently Asked Questions
- How do I test a regex pattern?
- Use StudioLimb's Regex Tester — paste your pattern and test string to see matches highlighted in real time. regex101.com is another excellent tool with explanation of each pattern component.
- What's the difference between greedy and lazy quantifiers?
- Greedy quantifiers (* + {n,m}) match as many characters as possible. Lazy quantifiers (*? +? {n,m}?) match as few as possible. For text, greedy <.*> matches the entire string; lazy <.*?> matches just .
- Are regex patterns the same in all languages?
- The core syntax is similar, but there are differences: named groups syntax varies ((?) in JS vs (?P) in Python), lookbehind support varies, and flags differ. Test your patterns in the target language, not just any online tool.
- Should I use regex or a library for email validation?
- For web forms: use a simple regex (like the example above) for immediate feedback, plus server-side email verification (send a confirmation email). The most robust validation is confirming the address actually receives email — no regex catches all edge cases.