« Previous
Next »
Summary
A final-page summary of the regex track: the constructs you reach for daily, the perf traps, and how to test what you write.
Regex — track summary
EXAMPLE
# ===== The constructs you reach for daily =====
# . any single char (except newline by default)
# ^ $ start / end of line (with /m), or string
# \b \B word boundary / not
# [...] character class; [^...] negated
# \d \w \s digit / word / whitespace ; \D \W \S inverse
# ? * + zero-or-one / zero-or-more / one-or-more
# {m,n} bounded repeat
# (?:...) non-capturing group
# (...) capturing group
# (?<name>...) named capture
# (?=...) positive lookahead
# (?!...) negative lookahead
# (?<=...) positive lookbehind
# (?<!...) negative lookbehind
# \1 backreference to group 1
# | alternation
# ===== Flags you reach for daily =====
# i case-insensitive
# m ^ and $ match per line
# s . matches newline
# g global (JS), or use re.finditer in Python
# u Unicode-aware (treat \w as Unicode letters etc.)
# x free-spacing (allow whitespace + comments in the pattern)
# ===== Patterns you actually use =====
# Email-ish: ^[^@\s]+@[^@\s]+\.[^@\s]+$
# URL host: ^https?://([^/]+)(/.*)?$
# ISO date: ^\d{4}-\d{2}-\d{2}$
# UUID v4: ^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
# Hex color: ^#([0-9a-f]{3}|[0-9a-f]{6})$
# IPv4: ^((25[0-5]|2[0-4]\d|[01]?\d?\d)\.){3}(25[0-5]|2[0-4]\d|[01]?\d?\d)$
# ===== Perf and safety =====
# Catastrophic backtracking happens when nested quantifiers overlap on the same input:
# ^(a+)+$ on input 'aaaaaaaaaaaaaaaaaaaaX' -> exponential time
#
# Mitigation:
# - Possessive quantifiers (++, *+, ?+) in PCRE/Java
# - Atomic groups (?>...)
# - Rewrite to avoid overlap: ^a+$ instead of ^(a+)+$
# - Use a non-backtracking engine (RE2 / Go / Rust regex crate)
# - On Node 22+: use the /v flag with linear-time engines where available
# ===== Testing what you write =====
# Always write a tiny test list with:
# - 2 positives
# - 2 negatives (close-but-no)
# - 1 obvious failure that should NOT match (helps catch greedy bugs)
# Example for the ISO date:
# yes: 2024-01-31, 1999-12-31
# no : 2024-1-31 (bad padding), 2024-01-32 (bad day but pattern still accepts -> add range checks)
# ===== Patterns to internalise =====
# - Anchors when you want exact match: always start with ^ and end with $
# - Non-capturing groups (?:...) by default; only capture what you read out
# - Named captures when there are more than two
# - Use a real parser for grammars (HTML, JSON, SQL). Regex is for tokens.
# ===== Pitfalls =====
# - .* across multiple lines without /s -> 'why doesn't it match?'
# - Greedy ranges in HTML -> use a parser
# - Unicode oversights: \w in JS without /u skips non-ASCII letters
# - Trusting regex for email validation in the way RFC 5321 defines it (just send the verification email)
# - Untested patterns in input validation -> bypasses or rejections of valid input
Why it matters
Regex is a power tool with sharp edges. Memorise the daily constructs, anchor strictly, test with a small list every time, and reach for a parser when grammars get nested. Catastrophic backtracking is not a folklore bug — it is a deploy-stopper waiting on the right input.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
// Next: lookbehind support quirks, RE2 in Node, parser-combinators when regex stops fitting.Try it Yourself »
« Previous
Next »
Discussion
Loading…