DevTools Hub
All guides

How to read a regular expression without panicking

Regex looks like line noise until you know the four things it is made of. A practical guide to reading any pattern, plus the mistakes that waste the most time.

4 August 20262 min read

A regular expression is not one language so much as four small ideas stacked together: literals, character classes, quantifiers and groups. Once you can name which part you are looking at, even an intimidating pattern becomes readable left to right.

The four building blocks

Literals match themselves — cat matches the letters c, a, t. Character classes, written in square brackets, match any one character from a set: [aeiou] is any vowel, and [a-z0-9] is any lowercase letter or digit. Shorthands like \d, \w and \s are just common classes with shorter names.

Quantifiers say how many times the thing before them may repeat. ? means zero or one, * means zero or more, + means one or more, and {2,4} means between two and four. Groups, written in parentheses, bundle part of a pattern so a quantifier applies to all of it — and capture what matched so you can pull it out afterwards.

Anchors are what stop false matches

^ matches the start of the string and $ the end. Without them a pattern can match anywhere inside a longer piece of text, which is the usual reason a validation regex accepts something it shouldn't. A pattern for a postcode that matches happily in the middle of a sentence is not validating anything.

\b is subtler: it matches the boundary between a word character and a non-word character, without consuming anything. It is the right tool when you want whole words rather than fragments — \bcat\b will not match inside concatenate.

The mistakes that cost the most time

Forgetting the global flag is the most common. Without g, only the first match is returned, which makes a perfectly correct pattern look broken. Next is greedy matching: .* takes as much as it possibly can, so <.*> applied to <a><b> matches the whole thing rather than just <a>. Adding ? makes a quantifier lazy — <.*?> does what most people intended.

The third is assuming regex dialects are interchangeable. JavaScript, Python, PCRE and .NET differ in lookbehind support, named group syntax and escape sequences. Test against the engine you will actually deploy to, not a different one that happens to be nearby.

In short

Read a pattern in pieces rather than as a whole, anchor anything meant to validate, and make quantifiers lazy when they overshoot. If a pattern still resists, paste it into the tester and read the explanation alongside the live matches.

Regex Tester

Test and explain regular expressions with real-time matching and plain English explanations.

Open the tool

Keep reading