模块概览
import re # 主要函数 re.match() # 从字符串开头匹配 re.search() # 在整个字符串中搜索 re.findall() # 找到所有匹配,返回列表 re.finditer() # 找到所有匹配,返回迭代器 re.sub() # 替换匹配内容 re.subn() # 替换并返回替换次数 re.split() # 按模式分割字符串 re.compile() # 预编译正则,提升重复使用性能 re.fullmatch() # 要求整个字符串完全匹配
match vs search vs fullmatch
import re s = 'hello world' re.match(r'world', s) # None(match 从开头开始) re.search(r'world', s) # Match(search 搜索整个字符串) re.fullmatch(r'hello.*', s) # Match(整个字符串必须匹配) # 实用建议:搜索用 search,验证格式用 fullmatch
Match 对象的方法
m = re.search(r'(\d+)-(\w+)', '编号 42-alpha 序列') if m: m.group() # '42-alpha' 整个匹配 m.group(0) # '42-alpha' 同上 m.group(1) # '42' 第1捕获组 m.group(2) # 'alpha' 第2捕获组 m.groups() # ('42', 'alpha') m.start() # 3 匹配开始位置 m.end() # 11 匹配结束位置 m.span() # (3, 11) m.string # '编号 42-alpha 序列' 原始字符串
findall 与 finditer
# findall 返回列表 re.findall(r'\d+', 'a1 b22 c333') # → ['1', '22', '333'] # 有捕获组时,返回捕获组内容的列表 re.findall(r'(\w+)=(\d+)', 'x=1 y=22') # → [('x', '1'), ('y', '22')] # finditer 返回 Match 对象迭代器(内存友好) for m in re.finditer(r'\d+', 'a1 b22 c333'): print(m.group(), m.start())
sub 替换
# 简单替换 re.sub(r'\s+', ' ', 'hello world') # → 'hello world' # 用捕获组重组 re.sub(r'(\w+)\s+(\w+)', r'\2 \1', 'hello world') # → 'world hello' # 限制替换次数 re.sub(r'\s', '-', 'a b c d', count=2) # → 'a-b-c d' # 用函数作为替换参数(动态替换) def upper_match(m): return m.group().upper() re.sub(r'\b\w{4}\b', upper_match, 'this is a test case') # → 'THIS is a TEST CASE'
split 分割
# 按空白分割 re.split(r'\s+', ' hello world ') # → ['', 'hello', 'world', ''] # 按多种分隔符分割(包含捕获组时,分隔符也出现在结果中) re.split(r'[,;]', 'a,b;c,d') # → ['a', 'b', 'c', 'd'] # 限制分割次数 re.split(r',', 'a,b,c,d', maxsplit=2) # → ['a', 'b', 'c,d']
编译与重用
# 预编译正则——在循环中大量使用时显著提升性能 pattern = re.compile(r'\d{4}-\d{2}-\d{2}', re.IGNORECASE) dates = ['2026-03-26', 'invalid', '2025-12-31'] for d in dates: m = pattern.fullmatch(d) if m: print(f'有效日期: {d}')
INFOPython 的
re 模块内部有一个编译缓存(默认 512 个),所以直接调用 re.search() 也会自动缓存编译结果。但对于需要重复调用的模式,显式 compile() 仍是最佳实践——既能提升性能,又让代码意图更清晰。常见陷阱
# 陷阱1:match 只从开头匹配 re.match(r'\d+', 'abc123') # None!不是 '123' re.search(r'\d+', 'abc123') # Match('123') # 陷阱2:贪婪导致过度匹配 re.findall(r'<.+>', '<a>text</a>') # ['<a>text</a>'] re.findall(r'<.+?>', '<a>text</a>') # ['<a>', '</a>'] # 陷阱3:忘记使用原始字符串 re.search("\d+", text) # 偶尔可能出现双重转义问题 re.search(r"\d+", text) # ✅ 始终使用 r"..." # 陷阱4:findall 有捕获组时行为不同 re.findall(r'\d+', 'a1 b2') # ['1', '2'] re.findall(r'(\d)+', 'a12 b34') # ['2', '4'](最后一个捕获) re.findall(r'(\d+)', 'a12 b34') # ['12', '34'](正确)
小结
search搜索整串;match只从开头;fullmatch要求整串匹配findall返回列表(有捕获组时返回元组列表);finditer返回迭代器sub支持字符串、反向引用\1和函数三种替换方式- 重复使用的模式应预先
compile();始终用r"..."原始字符串