← All posts

Regex without the headache: a practical field guide

Regex without the headache: a practical field guide

Regular expressions have a reputation, and it's mostly deserved. Stare at ^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$ cold and it reads like someone fell asleep on the keyboard. But the day-to-day stuff? Much smaller toolbox than the scary examples suggest.

We use regex constantly — renaming files, validating input, pulling fields out of logs — and almost always with the same handful of pieces. Here's the set worth memorizing first.

The pieces that cover most jobs

Character classes are the workhorses. \d matches a digit, \w a word character (letters, digits, underscore), \s whitespace. The capital versions invert them, so \D is "not a digit." Square brackets let you build your own: [aeiou] matches any vowel, [a-f0-9] any hex character.

Then come the quantifiers, which say how many. * is zero or more, + is one or more, ? is optional, and {2,4} is between two and four. Anchors pin things in place: ^ is the start of the line, $ the end. So ^\d{4}$ means exactly four digits and nothing else — handy for a PIN or a year.

A worked example

Say you want to pull dates like 2026-05-30 out of a wall of text. Start literal: four digits, a dash, two digits, a dash, two digits.

\d{4}-\d{2}-\d{2}

That already works. Want the year, month, and day separately? Wrap each part in parentheses to capture it:

(\d{4})-(\d{2})-(\d{2})

Now group one is the year, group two the month, group three the day. Most languages let you name them too, which saves you counting brackets later: (?<year>\d{4}). Future-you will be grateful.

The two traps everyone hits

First, greediness. By default .* grabs as much as it possibly can. Match <.*> against <a><b> and you get the whole thing, not just the first tag. Add a ? to make it lazy — <.*?> — and it stops at the first >.

Second, forgetting to escape. A dot means "any character," so when you actually want a literal period — in a file name or an IP address — you write \. instead. The number of "why does this match everything" bugs that trace back to one unescaped dot is genuinely funny, right up until it's your bug.

Test, don't guess

The fastest way to learn regex is to watch it match in real time instead of running your whole program over and over. Our regex tester highlights matches and capture groups as you type, so you can build a pattern one piece at a time and see what each change does. Start small, add a rule, check. The line noise starts to read like sentences.