search vs match, groups, findall/finditer, sub with backreferences, split, flags, and a pattern syntax reference.
import re
s = "Order 66 shipped 2026-09-26 to ada@example.com, ref AB-12"m = re.search(r"\d+", s); m.group()First match anywhere → '66'; None when nothing matches.
re.match(r"Order", s), re.match(r"\d+", s)match anchors at the START only → Match, None.
re.fullmatch(r"\d{4}-\d{2}-\d{2}", "2026-09-26")The whole string must match.
m.start(), m.end(), m.span()Where it matched → 6, 8, (6, 8).
bool(re.search(r"ship", s))Yes/no test.
if (m := re.search(r"ref (\w+)-(\d+)", s)):
print(m[1], m[2])Walrus + indexing → 'AB', '12'.
re.search(r"\d+", s).group(0)group(0) or [0] is the whole match.
m = re.search(r"(\d{4})-(\d{2})-(\d{2})", s)
m.group(1), m.groups()Numbered groups → '2026', ('2026', '09', '26').
m = re.search(r"(?P<year>\d{4})-(?P<month>\d{2})", s)
m.group("year"), m.groupdict()Named groups → '2026', {'year': '2026', 'month': '09'}.
re.search(r"(?:Order|Ref) (\d+)", s).group(1)(?:...) groups without capturing → '66'.
re.search(r"(\w)\1", "hello").group()Backreference: a repeated character → 'll'.
re.search(r"\d+", s).groups()No groups → ().
re.findall(r"\d+", s)All matches as strings → ['66', '2026', '09', '26', '12'].
re.findall(r"(\w+)@(\w+)", s)With groups, findall returns tuples → [('ada', 'example')].
[m.span() for m in re.finditer(r"\d+", s)]Match objects, lazily, with positions.
re.sub(r"\s+", " ", "a b \t c")Replace every match → 'a b c'.
re.sub(r"(\d{4})-(\d{2})-(\d{2})", r"\3/\2/\1", s)Backreferences in the replacement → '26/09/2026'.
re.sub(r"(?P<u>\w+)@", r"\g<u> at ", s)Named group in the replacement.
re.sub(r"\d+", lambda m: str(int(m.group()) * 2), "3 apples 4 pears")A function computes each replacement → '6 apples 8 pears'.
re.sub(r"\d", "#", s, count=2)Limit the number of replacements.
re.subn(r"\d+", "N", s)Result plus the number of substitutions.
re.split(r"[,;]\s*", "a, b;c ,d")Split on a pattern → ['a', 'b', 'c ', 'd'].
re.split(r"(\d+)", "a1b22c")A capturing group keeps the separators → ['a', '1', 'b', '22', 'c'].
DATE = re.compile(r"\d{4}-\d{2}-\d{2}")
DATE.search(s).group(), DATE.patternCompile once, reuse; same methods as the module functions.
re.findall(r"order", s, flags=re.IGNORECASE)re.I: case-insensitive → ['Order'].
re.findall(r"^\w+", "one\ntwo", re.MULTILINE)re.M: ^ and $ match at every line → ['one', 'two'].
re.search(r"a.b", "a\nb", re.DOTALL) is not Nonere.S: . also matches newline → True.
PAT = re.compile(r"""
(?P<user>[\w.]+) # local part
@
(?P<host>[\w.]+) # domain
""", re.VERBOSE)
PAT.search(s).group("host")re.X: whitespace and # comments ignored in the pattern.
re.search(re.escape("a+b (x)"), "sum a+b (x) here").group()Escape user input before putting it in a pattern.
re.findall(r"\w+", "café naïve", re.ASCII)By default \w is Unicode-aware; re.A restricts it to ASCII.
re.findall(r"\d \D \w \W \s \S", "1 a b ! \t x")digit / non-digit / word char / non-word / whitespace / non-space → the whole string matches.
re.findall(r"[A-Za-z]+", "abc DEF 123")Character class → ['abc', 'DEF']; [^0-9] negates.
re.findall(r"a{2}|b{1,3}|c+|d*e|f?g", "aa bbb cc de fg g")Exactly 2 / 1 to 3 / 1+ / 0+ / 0 or 1.
re.search(r"<.*>", "<a><b>").group(), re.search(r"<.*?>", "<a><b>").group()Greedy takes '<a><b>'; lazy *? takes '<a>'.
re.findall(r"^\w+|\w+$", "start middle end")^ start and $ end anchors → ['start', 'end'].
re.findall(r"\bcat\b", "cat concat cat.")\b word boundary → ['cat', 'cat'], skips 'concat'.
re.findall(r"\d+(?= USD)", "5 USD 7 EUR 9 USD")Lookahead: digits followed by ' USD' → ['5', '9'].
re.findall(r"(?<=\$)\d+", "$5 and 7 and $9")Lookbehind: digits preceded by $ → ['5', '9'].
re.findall(r"\d+(?! USD)\b", "5 USD 7 EUR")Negative lookahead → ['7'].
re.findall(r"cat|dog", "cat dog cow")Alternation → ['cat', 'dog'].
re.search(r"(\d+)\.(\d+)", "v3.12").groups()Escape a literal dot with \. → ('3', '12').
Want the topic explained, not just listed? The Regular Expressions lesson walks through it with graded exercises. Preparing for interviews? See the interview prep track.