re
A pattern language for text. search finds the first match, findall collects them all, sub replaces, split cuts — and every pattern belongs in a raw string: r'\d+', not '\d+'.
import re pattern = re.compile(r'\d+')
Demo
import re m = re.search('\\d{4}-\\d{2}-\\d{2}', 'Invoice due 2026-09-29, paid 2026-10-02') m.group() if m else None
The code shows each pattern the way Python's repr() writes it, so every backslash appears doubled: '\\d+' in the box is exactly the string you would type as r'\d+'. Two results worth a second look: findall with groups returns the groups, not the whole match, and splitting on whitespace leaves an empty string at each end when the text starts or ends with a separator.
Members
Common patterns
import re DATE = re.compile(r'(\d{4})-(\d{2})-(\d{2})') for line in lines: if m := DATE.search(line): year, month, day = m.groups()
import re def is_zip(s): return re.fullmatch(r'\d{5}(-\d{4})?', s) is not None
import re m = re.search(r'(?P<user>[\w.]+)@(?P<host>[\w.-]+)', text) if m: info = m.groupdict() # {'user': ..., 'host': ...}
import re BAD = re.compile(r'^(a+)+$') # near-misses like 'aaaa…ab' take exponential time GOOD = re.compile(r'^a+$') # same strings, linear ALSO = re.compile(r'^(?:a+)++$') # possessive: no backtracking into the group
import re PHONE = re.compile(r''' (\d{3}) # area code [-.\s]? (\d{4}) # number ''', re.VERBOSE)
Examples
Pitfalls
import re print(re.search('\bcat\b', 'a cat here'))
import re re.search(r'\bcat\b', 'a cat here')
import re re.match(r'\d+', 'order 66') is None
import re re.search(r'\d+', 'order 66').group()
import re re.search(r'\d+', 'none here').group()
import re m = re.search(r'\d+', 'none here') m.group() if m else 'no number'
When to use
- Finding text by shape rather than exact content: dates, IDs, emails, log fields
- Replacing or splitting with rules str.replace and str.split cannot express
- Extracting several parts at once with groups
- A fixed substring → in, str.find, str.replace, str.startswith (faster and clearer)
- Splitting on runs of whitespace → str.split() with no argument (drops the empty ends)
- HTML, JSON, CSV or other nested/quoted formats → a real parser (html.parser, json, csv)
Notes
FAQ
Because Python processes backslash escapes in normal strings first. '\b' becomes a backspace, '\1' becomes the character with code 1, and unknown escapes like '\d' raise a SyntaxWarning since Python 3.12. In r'\b\d+' every backslash reaches the regex engine unchanged.