Regular expressions have a reputation for looking like line noise — a wall of symbols that seems to mean nothing until you've memorized it. But the underlying idea is simple: a regex is just a pattern that describes what text you're looking for, built up piece by piece from a small set of building blocks. Once you know the blocks, the wall of symbols starts reading like a sentence.

Start with literal characters

The simplest regex is just the text you want to find. The pattern cat matches the literal characters "cat," wherever they appear. That's already a regex, even without any special symbols.

The dot: match almost anything

A period . matches any single character except a newline. So the pattern c.t matches "cat," "cot," "c9t," or "c t" — anything with a "c," then any one character, then a "t."

Character classes: match one of a set

Square brackets let you specify a set of acceptable characters for one position. [aeiou] matches exactly one vowel. [0-9] matches exactly one digit (the hyphen inside brackets defines a range). You can combine ranges: [a-zA-Z] matches any single letter, upper or lowercase.

A few character classes come up so often they have shorthand:

ShorthandMeansEquivalent to
\da digit[0-9]
\wa "word" character[a-zA-Z0-9_]
\swhitespacespace, tab, newline

Capitalizing each of these negates it: \D matches anything that's not a digit, and so on.

Quantifiers: how many times

By default, each part of a pattern matches exactly once. Quantifiers change that:

Putting a few of these together: \d+ matches one or more digits in a row — a whole number, essentially.

Anchors: position, not characters

^ matches the start of the string (or line, with the multiline flag), and $ matches the end. They don't consume any characters themselves — they just assert a position. The pattern ^https:// matches only if the string literally begins with "https://," not if that text appears somewhere in the middle.

Groups: treating several characters as one unit

Parentheses ( ) group part of a pattern together, which lets you apply a quantifier to the whole group rather than just one character, and also lets you extract that specific piece of the match separately (a "capture group"). (ab)+ matches "ab," "abab," "ababab" — the whole two-character unit repeating, not just the "b."

Putting it together: matching an email address

A commonly used (if imperfect) email-matching pattern:

\b[\w.+-]+@[\w-]+\.[a-zA-Z]{2,}\b

Read piece by piece:

This is exactly how a seemingly intimidating pattern is actually built: small, individually simple pieces, placed next to each other.

Common flags

A genuinely useful habit: build patterns incrementally

Nobody writes a complex regex correctly in one attempt, and that's completely normal. Start with the simplest piece of what you're trying to match, test it against real sample text, confirm it works, then add the next piece. A regex tester that highlights matches live as you build the pattern turns this from guesswork into a fast, visual feedback loop.

When not to reach for regex

Regex is great for pattern matching in relatively simple, well-defined text. It's a poor tool for parsing genuinely nested or structured formats like HTML, JSON, or XML — those have rules (matching tags, nested brackets) that regex fundamentally isn't designed to track. If you're tempted to parse JSON or HTML with a regex, use an actual parser instead; you'll save yourself from a long list of edge cases regex simply can't handle correctly.

Frequently Asked Questions

* means “zero or more” of the preceding element, so it matches even if that element isn't present at all. + means “one or more,” requiring at least one occurrence.
You likely need the global flag (g) turned on. Without it, most regex engines stop after finding the first match instead of continuing to search the rest of the string.
It's a word boundary — a zero-width assertion that matches the position between a word character and a non-word character (or the start/end of the string). It's commonly used to make sure a pattern matches a whole word rather than part of a longer one.
It's commonly used for a basic sanity check, but no regex perfectly validates every technically-legal email address per the full email specification. For anything where correctness really matters, pair a reasonable regex check with actually sending a verification email.