Regex Cheat Sheet: Patterns Every Developer Needs

· Javed Iqbal · 10 min read

Regex is write-only for most of us. You spend twenty minutes crafting the perfect pattern, it works, and three months later you stare at it like it is hieroglyphics. So this is the page I keep bookmarked: the tokens grouped the way I actually think about them, plus the handful of patterns I copy and paste over and over.

Everything here is standard JavaScript regex (the flavor in the browser and Node), and it is close enough to PCRE that it carries over to most languages.

Anchors and boundaries

^Start of the string (or line, with the m flag)
$End of the string (or line, with the m flag)
\bWord boundary (edge of a word)
\BNot a word boundary

Character classes

.Any character except a newline
\dA digit, same as [0-9]
\DAny non-digit
\wA word character, [A-Za-z0-9_]
\WAny non-word character
\sWhitespace (space, tab, newline)
\SAny non-whitespace
[abc]Any one of a, b, or c
[^abc]Any character except a, b, or c
[a-z]Any character in the range a to z

Quantifiers (how many)

*Zero or more
+One or more
?Zero or one (optional)
{3}Exactly 3
{3,}3 or more
{2,4}Between 2 and 4
*?Lazy: match as few as possible (any quantifier + ?)

Greedy vs lazy trips everyone up. By default quantifiers are greedy: <.+> on <a><b> matches the whole thing, not just <a>. Add a ? to make it lazy: <.+?> stops at the first >.

Groups and alternation

(abc)Capturing group (you can reference it later)
(?:abc)Non-capturing group (group without capturing)
(?<name>abc)Named capturing group
a|bMatch a or b (alternation)
\1Backreference to the first captured group

Lookarounds

(?=abc)Lookahead: followed by abc
(?!abc)Negative lookahead: not followed by abc
(?<=abc)Lookbehind: preceded by abc
(?<!abc)Negative lookbehind: not preceded by abc

Flags

gGlobal: find all matches, not just the first
iCase-insensitive
mMultiline: ^ and $ match line starts/ends
sDotall: . also matches newlines
uUnicode mode
ySticky: match from lastIndex only

Copy-paste patterns

The ones I actually reuse. Test them against your real data before you ship (see the caveat below):

MatchesPattern
Email (sanity check)^[^@\s]+@[^@\s]+\.[^@\s]+$
URL (http/https)https?://[^\s]+
Hex color#?([0-9a-fA-F]{6}|[0-9a-fA-F]{3})
Digits only^\d+$
Date (YYYY-MM-DD)\d{4}-\d{2}-\d{2}
US phone (loose)\d{3}[-.\s]?\d{3}[-.\s]?\d{4}
IPv4 (loose)(\d{1,3}\.){3}\d{1,3}
Leading/trailing spaces^\s+|\s+$
URL slug[a-z0-9]+(?:-[a-z0-9]+)*

Test it before you trust it

Every pattern above is a starting point, not a guarantee. Regex is famous for the edge case you did not think of, so paste your pattern and a chunk of real sample text into the regex tester and watch what it highlights. Live match highlighting is the fastest way to find the input that breaks your pattern before your users do.

Two honest warnings

  • Do not fully validate emails with regex. The real email spec is enormous, and a strict pattern rejects valid addresses. Use the simple sanity-check pattern above, then confirm by sending a verification email. That is the only real validation.
  • Do not parse HTML with regex. HTML is not a regular language, so a regex will always miss nesting and edge cases. Use a parser (the DOM, a real HTML library) instead. Regex is for simple, flat text patterns.

FAQ

What is the difference between greedy and lazy?

Greedy quantifiers match as much as possible; lazy ones (add a ?) match as little as possible. Use lazy when you want the shortest match, like content between two tags.

When should I use a non-capturing group?

Use (?:...) when you need to group for alternation or quantifiers but do not want to capture the result. It keeps your capture group numbers clean and is slightly faster.

Does JavaScript support lookbehind?

Yes. Modern JavaScript engines support both lookahead and lookbehind. If you target very old environments, test first.

Why does my pattern match too much?

Almost always a greedy quantifier. Make it lazy by adding ?, or tighten the character class so it cannot cross the boundary you care about.

Grab a pattern above, then drop it into the regex tester with your real text to see exactly what it matches.