Regular expressions have a reputation for being cryptic, but 90% of real-world use boils down to a handful of patterns that repeat across every project: validating an email, extracting a URL, cleaning up duplicate whitespace. The rest is Googling when the odd edge case shows up.
Test before you ship it
Before dropping a regex into your code, test it against several real cases — including ones that shouldn't match — in the regex tester. It highlights every match and captured group, so you immediately see if the pattern is too loose or too strict.
The patterns you'll always need
- Email (basic validation):
^[^\s@]+@[^\s@]+\.[^\s@]+$— doesn't cover 100% of the RFC, but it's enough for forms. - Digits only:
^\d+$ - Duplicate whitespace:
\s{2,}— handy for cleaning up text pasted from a PDF or Word. - URL with protocol:
^https?:\/\/[^\s]+$ - ISO date (YYYY-MM-DD):
^\d{4}-\d{2}-\d{2}$ - Slug (lowercase and hyphens):
^[a-z0-9]+(-[a-z0-9]+)*$
The most common mistakes
- Forgetting to escape the dot.
.means "any character," not a literal period. For a domain, it's\.not. - Greedy by default.
<.+>against<b>bold</b>matches from the first<to the very last>, not just one tag. Use the lazy quantifier<.+?>to stop at the first closing tag. - Not anchoring the pattern. Without
^and$, your regex can match part of the string and let junk slip through before or after. - Confusing
[abc]with(abc). The first means "one of these three letters"; the second means "the exact sequence abc" as a group.
Named groups, your best friend
When extracting several values from a string (parts of a URL, a date), use named groups instead of counting by position: (?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2}). The code consuming the result becomes far more readable than match[1], match[2], match[3].
The short version: write the pattern, test it against real edge cases, and only then paste it into your code.

