re — regular expressions#
Part of a series demonstrating the 5 most-imported modules across the top PyPI packages (from imports_ranked.csv). Rank 5 of 5 — imported by 60.6% of crawled packages.
Pattern matching and text extraction. Core functions: search, match, fullmatch, findall, finditer, sub, split, and compile.
search vs match vs fullmatch#
match anchors at the start, fullmatch must consume the whole string, search scans anywhere.
import re
s = 'order 12345 shipped'
print('search :', re.search(r'\d+', s))
print('match :', re.match(r'\d+', s)) # None: starts with letters
print('match :', re.match(r'\w+', s)) # matches 'order'
print('fullmatch:', re.fullmatch(r'[\w ]+', s))
search : <re.Match object; span=(6, 11), match='12345'>
match : None
match : <re.Match object; span=(0, 5), match='order'>
fullmatch: <re.Match object; span=(0, 19), match='order 12345 shipped'>
Capturing groups — named and numbered#
import re
m = re.search(r'(?P<year>\d{4})-(?P<month>\d{2})', '2026-08 report')
print('group(0):', m.group(0))
print('year :', m.group('year'))
print('month :', m.group(2))
print('groupdict:', m.groupdict())
group(0): 2026-08
year : 2026
month : 08
groupdict: {'year': '2026', 'month': '08'}
findall and finditer — all matches#
import re
text = 'contact ada@x.io or linus@y.org today'
print('findall :', re.findall(r'[\w.]+@[\w.]+', text))
for m in re.finditer(r'[\w.]+@[\w.]+', text):
print(f' {m.group()} at [{m.start()}:{m.end()}]')
findall : ['ada@x.io', 'linus@y.org']
ada@x.io at [8:16]
linus@y.org at [20:31]
sub and split — replace and tokenise#
import re
print(re.sub(r'\s+', '_', 'a b \t c')) # collapse whitespace
print(re.sub(r'(\w+)@\w+', r'\1@***', 'bob@corp')) # backreference
print(re.split(r'[,;\s]+', 'a, b;c d')) # split on any delimiter
a_b_c
bob@***
['a', 'b', 'c', 'd']
compile and flags#
Compile once, reuse many times. Flags like IGNORECASE and MULTILINE tune matching.
import re
pat = re.compile(r'^error', re.IGNORECASE | re.MULTILINE)
log = 'Error: disk full\nok\nERROR: timeout'
print('matches:', pat.findall(log))
print('count :', len(pat.findall(log)))
matches: ['Error', 'ERROR']
count : 2
Escaping literal text: re.escape#
Safely match strings that contain regex metacharacters.
import re
user_input = 'a.b*c'
print('escaped:', re.escape(user_input))
print('found :', bool(re.search(re.escape(user_input), 'xa.b*cy')))
escaped: a\.b\*c
found : True