Master regular expressions with practical patterns. Learn lookaheads, backreferences, named groups, Unicode support, and real-world regex solutions for common tasks.
Regular Expressions: Practical Guide
Essential Patterns
// Email validation (practical, not RFC 5321 compliant)
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$/
// URL matching
const urlRegex = /https?://(www.)?[-a-zA-Z0-9@:%._+~#=]{1,256}.[a-zA-Z0-9()]{1,6}([-a-zA-Z0-9()@:%_+.~#?&//=]*)/
// IP address (IPv4)
const ipv4Regex = /^(d{1,3}.){3}d{1,3}$/
// Stricter version with range validation
const strictIpv4Regex = /^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
// Phone numbers (US format)
const phoneRegex = /^(+1)?s?((d{3})|d{3})[s.-]?d{3}[s.-]?d{4}$/
// Strong password
const passwordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*d)(?=.*[@$!%*?&])[A-Za-zd@$!%*?&]{8,}$/
// Credit card (major cards)
const creditCardRegex = /^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13}|6(?:011|5[0-9]{2})[0-9]{12})$/
Advanced Features
// Named capture groups
const dateRegex = /(?<year>d{4})-(?<month>d{2})-(?<day>d{2})/
const match = '2026-01-15'.match(dateRegex)
const { year, month, day } = match.groups // { year: '2026', month: '01', day: '15' }
// Lookaheads and Lookbehinds
// Positive lookahead: foo(?=bar) - foo followed by bar
const priceRegex = /d+(?=s*USD)/ // Numbers followed by USD
'100 USD 200 EUR'.match(priceRegex) // ['100']
// Negative lookahead: foo(?!bar) - foo NOT followed by bar
const nonNegative = /d+(?!s*USD)/ // Numbers NOT followed by USD
// Positive lookbehind: (?<=foo)bar - bar preceded by foo
const afterDollar = /(?<=$)d+(?:.d{2})?/ // Numbers after $
'$100.50'.match(afterDollar) // ['100.50']
// Negative lookbehind: (?<!foo)bar
const notAfterDollar = /(?<!$)d+/
// Non-capturing groups
const nonCapturing = /(?:https?|ftp):///
Real-World Patterns
// Parse log lines
const logRegex = /^(?<timestamp>d{4}-d{2}-d{2}T[d:.]+Z)s+(?<level>ERROR|WARN|INFO|DEBUG)s+(?<service>w+)s+-s+(?<message>.+)$/
const log = '2026-01-15T10:30:00Z ERROR auth - Login failed for user@example.com'
const { timestamp, level, service, message } = log.match(logRegex)?.groups ?? {}
// Extract query parameters
function parseQueryString(qs: string): Record<string, string> {
const params: Record<string, string> = {}
const regex = /[?&]?([^=]+)=([^&]*)/g
let match
while ((match = regex.exec(qs)) !== null) {
params[decodeURIComponent(match[1])] = decodeURIComponent(match[2])
}
return params
}
// Camel case to kebab case
const toKebab = (str: string) => str
.replace(/([a-z])([A-Z])/g, '$1-$2')
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2')
.toLowerCase()
// toKebab('camelCaseString') => 'camel-case-string'
// Truncate words (not characters)
const truncateWords = (text: string, maxWords: number) =>
text.split(/s+/).slice(0, maxWords).join(' ') +
(text.split(/s+/).length > maxWords ? '...' : '')
// Remove duplicate whitespace
const normalize = (s: string) => s.replace(/s+/g, ' ').trim()
// Extract mentions and hashtags
const mentions = (text: string) => [...text.matchAll(/@(w+)/g)].map(m => m[1])
const hashtags = (text: string) => [...text.matchAll(/#(w+)/g)].map(m => m[1])
Python Regex Patterns
import re
# Compile for performance (reuse)
email_pattern = re.compile(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}#39;)
# All matches
def extract_ips(text: str) -> list[str]:
pattern = re.compile(r'(?:d{1,3}.){3}d{1,3}')
return pattern.findall(text)
# Substitution with function
def mask_sensitive(text: str) -> str:
def mask_email(m):
parts = m.group().split('@')
return parts[0][:2] + '***@' + parts[1]
return re.sub(r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}', mask_email, text)
# Named groups
def parse_log(line: str) -> dict | None:
pattern = re.compile(
r'(?P<ip>d+.d+.d+.d+) .+ "(?P<method>GET|POST|PUT|DELETE) (?P<path>/S*)'
)
m = pattern.search(line)
return m.groupdict() if m else None
# Flags
text = "Hello World hello"
re.findall(r'hello', text, re.IGNORECASE) # ['Hello', 'hello']
re.match(r'.*', multiline_text, re.DOTALL | re.MULTILINE)
Regex Testing and Debugging
// Create reusable validator
function createValidator(pattern: RegExp, message: string) {
return (value: string) => ({
valid: pattern.test(value),
message: pattern.test(value) ? '' : message,
})
}
const validateEmail = createValidator(
/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$/,
'Invalid email format'
)
// Debug complex regex
function debugRegex(pattern: RegExp, input: string) {
const match = pattern.exec(input)
if (!match) return { matched: false }
return {
matched: true,
fullMatch: match[0],
groups: match.groups,
captures: match.slice(1),
index: match.index,
}
}
Common Gotchas
| Issue |
Solution |
| Greedy vs lazy |
Use .*? for lazy |
| Special chars |
Escape with `` |
| Performance |
Compile patterns once |
| Catastrophic backtrack |
Atomic groups or possessive |
| Unicode |
Use /u flag in JS |