The building blocks
A handful of symbols cover most everyday regex needs: \d matches any digit, \w matches any word character (letters, digits, underscore), \s matches any whitespace, and . matches any character except a newline (unless the dot-all flag is set). Adding a quantifier controls repetition: + means one or more, * means zero or more, ? means zero or one, and {n,m} means between n and m repetitions. Combining these covers a surprising amount of ground — \d+ matches one or more digits in a row, \w+@\w+ roughly matches a simplified email shape.
Anchors and boundaries
^ anchors a match to the start of the string (or line, with the multiline flag), and $ anchors to the end. \b marks a word boundary — the transition between a word character and a non-word character — which is what keeps a pattern like \bcat\b from matching "cat" inside "category." Forgetting these anchors is one of the most common reasons a pattern matches more (or less) than intended, since without them a pattern is free to match anywhere inside a larger string.
Test a pattern live
A few patterns worth having on hand
A simplified email shape: \b[\w.-]+@[\w.-]+\.\w+\b — good enough for most everyday validation, though genuinely complete email validation per spec is far more complex than most use cases actually need. A basic URL start: https?:\/\/[\w.-]+. Digits only: ^\d+$ (anchored, so it rejects anything with non-digit characters anywhere in the string). Whitespace trimming detection: ^\s+|\s+$ matches leading or trailing whitespace, useful for a find-and-clean pass.
Why testing a pattern before shipping it matters
Regex is unforgiving in a specific way: a subtly wrong pattern doesn't throw an error, it just silently matches the wrong thing, which can slip through code review and only surface later against real-world input the original test cases didn't cover. Running a pattern against a handful of realistic test strings — including edge cases and inputs specifically designed to break it — before it goes into a form validator or data-processing pipeline catches this class of bug far earlier and far more cheaply than debugging it in production.
When not to reach for regex
Regex is well-suited to bounded, well-defined patterns, but it's the wrong tool for anything with real nested or recursive structure — parsing HTML, JSON, or programming language syntax with regex alone is a well-known trap that tends to work for simple cases and then breaks unpredictably on anything more complex. For genuinely structured data, a proper parser is the right tool; regex is best kept for extracting or validating a specific, flat text pattern.