Zum Hauptinhalt springen

Regex cheat sheet: syntax, quantifiers and common patterns

8 Min. Lesezeit

Every character class, anchor, quantifier and group in one place, with ready-to-use patterns and the differences between JavaScript, Python, PHP and grep.

This is a regex cheat sheet: the character classes, anchors, quantifiers and groups that make up almost every regular expression, in one place. The building blocks are the same across JavaScript, Python, PHP, Java and grep, so learn them once and reuse them everywhere. The differences between those flavors are covered at the end.

Character classes

A character class matches a single character from a set. The backslash shorthands are the ones you will reach for most.

.        any character except newline
\d       a digit, 0-9
\D       any non-digit
\w       a word character: a-z A-Z 0-9 _
\W       any non-word character
\s       whitespace: space, tab, newline
\S       any non-whitespace
[abc]    exactly one of a, b or c
[^abc]   any one character except a, b or c
[a-z]    any lowercase letter (a range)
[0-9a-f] one hex digit (ranges combine)

Inside square brackets most metacharacters lose their special meaning, so [.?*] matches a literal dot, question mark or asterisk. A ^ as the first character negates the class.

Anchors and boundaries

Anchors match a position rather than a character, so they consume no text.

^        start of the string (or line, in multiline mode)
$        end of the string (or line, in multiline mode)
\b       a word boundary (edge of a \w run)
\B       not a word boundary
\A       start of the whole string (Python, PHP, Java)
\z       end of the whole string (PHP, Java)

\bcat\b matches cat as a whole word but not the cat inside category. This is the fix for the classic “my pattern matches too much” problem. Python writes the absolute end-of-string anchor as uppercase \Z rather than \z.

Quantifiers

Quantifiers say how many times the preceding token may repeat. By default they are greedy (match as much as possible); add a ? to make them lazy (as little as possible).

*        zero or more
+        one or more
?        zero or one (optional)
{3}      exactly 3
{2,}     2 or more
{2,4}    between 2 and 4
*?  +?   lazy versions (match the fewest)

The greedy/lazy distinction matters most with .. On the string <a><b>, the pattern <.*> matches the whole thing, while <.*?> matches just <a>.

Groups and alternation

(abc)      a capturing group, remembered as group 1
(?:abc)   a non-capturing group (grouping only)
(?<year>\d{4})  a named group, referenced as "year"
a|b       alternation: match a OR b
(cat|dog) group the alternation so it is scoped
\1        a backreference to what group 1 matched

Use a plain group ( ) when you want to extract the matched text, and a non-capturing group (?: ) when you only need to apply a quantifier or alternation to a chunk. Named groups make captures readable when a pattern has several.

Lookaround

Lookaround asserts that something is (or is not) next to the current position without including it in the match.

(?=abc)    lookahead: followed by abc
(?!abc)    negative lookahead: not followed by abc
(?<=abc)   lookbehind: preceded by abc
(?<!abc)   negative lookbehind: not preceded by abc

Example: \d+(?= ?USD) matches the number in 50 USD but leaves USD out of the result.

Flags

i    case-insensitive
g    global, all matches (JavaScript; Python uses findall, PHP preg_match_all)
m    multiline: ^ and $ match at line breaks
s    dotall: . also matches newlines
x    extended: ignore whitespace in the pattern (Python/PHP)

Ready-to-use patterns

Copy these as starting points, then test them against your real data rather than trusting them blindly. A “correct” email or URL regex does not really exist; these are pragmatic and good enough for validation.

^\d{4}-\d{2}-\d{2}$            an ISO date, 2026-09-26
^[\w.+-]+@[\w-]+\.[\w.-]+$      a simple email
^https?://[^\s]+$              an http(s) URL
^#?[0-9a-fA-F]{6}$             a hex color, #1a2b3c
^\+?[\d ()-]{7,}$              a loose phone number
\b\d{1,3}(\.\d{1,3}){3}\b      a loose IPv4 (does not cap octets at 255)

JavaScript vs. Python vs. PHP vs. grep

The tokens above are shared. What changes is how you write and run the pattern:

  • JavaScript. A literal between slashes with flags after: /\d+/g. Use str.match(), str.replace() or regex.test(). Named groups and lookbehind are supported in modern engines.
  • Python. Patterns are strings, so use a raw string to avoid double backslashes: re.findall(r"\d+", text). Flags are passed as arguments (re.IGNORECASE) or inline as (?i).
  • PHP. The pattern is a delimited string with flags after the closing delimiter: preg_match('/\d+/i', $text). PHP uses the PCRE engine, the most feature-rich of the four.
  • grep. Basic grep needs \+ and \? escaped; use grep -E (or egrep) for the modern syntax shown here, and grep -P for full Perl-style features like lookaround.

The reliable way to build a pattern is to write a little, test against real samples, then add to it. Paste your expression and some sample text into our free regex tester to see every match and capture group highlighted live, entirely in your browser.

Häufig gestellte Fragen

What does \d, \w and \s mean in regex?
\d matches a digit (0–9), \w matches a word character (letters, digits and underscore), and \s matches any whitespace (space, tab, newline). Their uppercase versions are the exact opposites: \D is any non-digit, \W any non-word character, and \S any non-whitespace.
What is the difference between * , + and ? in regex?
They are quantifiers that say how many times the thing before them may repeat. * means zero or more, + means one or more, and ? means zero or one (optional). Add a ? after any of them (*?, +?) to make it lazy, matching as little as possible instead of as much.
How do I match a literal dot or other special character?
Escape it with a backslash. A bare . matches any character, so to match a real full stop you write \. . The same applies to other metacharacters: \* , \+ , \? , \( , \[ and \\ for a literal backslash.
Is regex syntax the same in JavaScript, Python and PHP?
The core syntax (character classes, quantifiers, groups, anchors) is shared, so most patterns move between them unchanged. The differences are at the edges: how you write the pattern (a /.../ literal in JavaScript, a string in Python, a delimited string in PHP), how flags are passed, and support for newer features like named groups and lookbehind.