Core answer: Regular expressions match text by pattern: \d+ matches digits, \w+ word chars, . any char, * zero-or-more, + one-or-more, ? optional, {n,m} counted, [abc] a set, ^ $ anchors, ( ) groups. A phone regex ^1[3-9]\d{9}$ matches Chinese mobiles. Regex is a chainsaw: perfect for log scraping and validation, wrong for parsing HTML/JSON — use real parsers there.

The 20-token survival kit

TokenMeaningExample match
\d \Ddigit / non-digit"5"
\w \Wword char [A-Za-z0-9_] / not"a_1"
\s \Swhitespace / not" "
.any char except newline"x"
* + ?0+ / 1+ / 0-1 times"aaa"
{2,4}2 to 4 times"aaa"
[abc] [^abc]set / negated set"b"
^ $string start / endanchors
(abc)capture groupcaptures
(?:abc)non-capturing groupgroups
abalternation"a" or "b"
\bword boundarybetween \w and \W

Worked examples

Example 1 — Chinese mobile. ^1[3-9]\d{9}$ — starts with 1, second digit 3–9, then 9 digits. Test: 13812345678 ✓, 12345678901 ✗.

Example 2 — Email (pragmatic). ^[\w.+-]+@[\w-]+\.[\w.]+$ — deliberately loose; RFC-5322-complete regexes run 6,000+ chars and still annoy users. Validate format loosely, confirm by sending email.

Example 3 — Extract dates from logs. (\d{4})-(\d{2})-(\d{2}) captures year/month/day groups: "2025-01-15" → group(1)="2025".

Example 4 — Greedy vs lazy. For "ab", .* greedily eats the whole string; .*? lazily matches each tag separately. The ? after a quantifier flips greediness — the fix for 90% of "regex matched too much".

Example 5 — Catastrophic backtracking. ^(a+)+$ on "aaaaaaaaaaaaaaaaaaaaaaX" explores exponential paths and hangs for years. Avoid nested quantifiers over overlapping classes; possessive/atomic groups or simpler patterns fix it.

Common mistakes and myths

  1. Parsing HTML with regex — nested, malformed, commented markup defeats regex provably; use a parser (the famous Stack Overflow answer applies).
  2. Forgetting to escape dots — "a.com" also matches "axcom"; write a\.com for the literal dot.
  3. Assuming ^$ per line — without the m flag, ^$ match string edges only; "line 2" won't match ^line in multiline text.
  4. Unicode blindness — \w in many engines skips Chinese; use Unicode-aware flags/classes (\p{L} where supported) for international text.
  5. Reinventing validation — URLs, emails, IPs have battle-tested libraries; a hand-rolled regex is usually wrong in one edge case that matters.