Python Regex Cheat Sheet
Python's re module covering core matching functions, common metacharacters, capture groups, and compiled patterns with flags.
Core re Functions
The most-used entry points into the re module.
import rere.match(r"\d+", "123abc") # matches only at the startre.search(r"\d+", "abc123") # matches anywhere in the stringre.findall(r"\d+", "a1b22c333") # ['1', '22', '333']re.sub(r"\d+", "#", "a1b22c") # 'a#b#c're.split(r"\s+", "a b c") # ['a', 'b', 'c']
Common Metacharacters & Classes
Building blocks for constructing patterns.
- \d / \D- digit / non-digit character
- \w / \W- word character [a-zA-Z0-9_] / non-word character
- \s / \S- whitespace / non-whitespace character
- ^ / $- start of string (or line) / end of string (or line)
- . - any character except newline (unless re.DOTALL)
- * / + / ?- zero-or-more / one-or-more / zero-or-one repetition
- {m,n}- between m and n repetitions of the preceding token
- [abc] / [^abc]- character class matching / negated character class
Groups & Named Groups
Capturing and extracting parts of a match.
m = re.match(r"(\d{4})-(\d{2})-(\d{2})", "2024-01-15")m.group(0) # '2024-01-15' (whole match)m.group(1) # '2024'm.groups() # ('2024', '01', '15')m = re.match(r"(?P<year>\d{4})-(?P<month>\d{2})", "2024-01")m.group("year") # '2024'm.groupdict() # {'year': '2024', 'month': '01'}
Compiling Patterns & Flags
Reusing patterns efficiently and modifying match behavior.
pattern = re.compile(r"\d+")pattern.findall("A1 b2") # ['1', '2']re.search(r"hello", "HELLO WORLD", re.IGNORECASE)re.findall(r"^\w+", "line1\nline2", re.MULTILINE)re.match(r"a.b", "a\nb", re.DOTALL) # . also matches newline
Lookahead & Lookbehind Assertions
Zero-width assertions that match a position without consuming characters.
import re# Positive lookahead: digits followed by 'px're.findall(r"\d+(?=px)", "10px 20em 30px") # ['10', '30']# Negative lookahead: word not followed by '!'re.findall(r"\b\w+\b(?!!)", "hi! bye")# Positive lookbehind: digits preceded by '$'re.findall(r"(?<=\$)\d+", "$100 and 200") # ['100']# Negative lookbehind: digits not preceded by '$'re.findall(r"(?<!\$)\b\d+\b", "$100 and 200") # ['200']
Non-Greedy Quantifiers & Backreferences
Controlling match length and re-matching a previously captured group.
re.findall(r"<.+>", "<a><b>") # ['<a><b>'] -- greedy, matches too muchre.findall(r"<.+?>", "<a><b>") # ['<a>', '<b>'] -- lazy, stops at first '>'# Backreference: match a repeated wordre.search(r"\b(\w+)\s+\1\b", "hello hello world") # matches 'hello hello'# Named backreferencere.search(r"(?P<w>\w+) (?P=w)", "go go!")
re.sub with a Function & Backreferences
Replace matches dynamically using a callback, or reference captured groups in the replacement.
import re# Replacement string referencing groups by numberre.sub(r"(\w+)@(\w+)", r"\2@\1", "user@host") # 'host@user'# Replacement via callback functiondef upper_match(m): return m.group(0).upper()re.sub(r"\b[a-z]+\b", upper_match, "hello world") # 'HELLO WORLD'# count limits how many substitutions occurre.sub(r"a", "X", "aaa", count=1) # 'Xaa'
re.finditer & Match Spans
Iterate over matches lazily while retrieving their exact position in the string.
text = "cat hat bat"for m in re.finditer(r"\w+at", text): print(m.group(), m.start(), m.end(), m.span())# cat 0 3 (0, 3)# hat 4 7 (4, 7)# bat 8 11 (8, 11)# Useful for building diagnostics/highlighters without materializing a full list
Advanced Regex Reference
Lesser-known constructs and performance-relevant behaviors of the re module.
- (?:...)- non-capturing group, groups a pattern for alternation/quantifiers without creating a capture slot
- (?i:...) / (?m:...)- scoped inline flags (Python 3.11+) applying a flag to only part of the pattern
- re.VERBOSE (re.X)- allows whitespace and # comments in a pattern for readability
- catastrophic backtracking- nested quantifiers like (a+)+ on adversarial input can cause exponential-time matching; avoid ambiguous nested repetition
- re.Match.groupdict(default=None)- returns named groups as a dict, filling unmatched optional groups with default
- str.translate + str.maketrans- faster than regex for simple fixed character-to-character substitutions
- regex module (third-party)- drop-in re replacement adding variable-length lookbehind, fuzzy matching, and possessive quantifiers
Always use raw strings (r"...") for regex patterns — without the r prefix, Python's own backslash escaping (like \d being interpreted before the regex engine sees it) can silently produce a different pattern than the one you wrote.