HoRain云--Python正则表达式完全指南:从基础到高性能匹配

发布时间:2026/10/21 11:37:27
HoRain云--Python正则表达式完全指南:从基础到高性能匹配
正则表达式是文本处理的利器但写不好会带来性能问题和难以调试的Bug。本文从基础语法到高级技巧再到性能优化和常见陷阱系统讲解Python正则。一、re模块基础python复制下载import re text 我的电话是 138-1234-5678邮箱 testexample.com # 查找第一个 m re.search(r\d{3}-\d{4}-\d{4}, text) if m: print(m.group()) # 138-1234-5678 print(m.span()) # (7, 20) # 查找全部 phones re.findall(r\d{3}-\d{4}-\d{4}, text) # 匹配开头 if re.match(r我的, text): print(以我的开头) # 全字符串匹配 if re.fullmatch(r\d, 12345): print(全是数字) # 替换 new re.sub(r\d{4}, ****, text) # 分割 parts re.split(r[,;], a,bc,d)二、编译正则提升性能重复使用同一正则时预编译python复制下载import re # 不推荐每次调用都编译 def bad(): for line in lines: if re.search(rERROR|WARN, line): ... # 推荐预编译 PATTERN re.compile(rERROR|WARN) def good(): for line in lines: if PATTERN.search(line): ...re模块内部有缓存默认512个但显式编译更清晰。三、核心语法速查python复制下载# 字符类 r[abc] # a或b或c r[^abc] # 非a、b、c r[a-z] # 小写字母 r\d # 数字 [0-9] r\w # 单词字符 [a-zA-Z0-9_] r\s # 空白 # 量词 ra* # 0或多次 ra # 1或多次 ra? # 0或1次 ra{3} # 恰好3次 ra{2,5} # 2到5次 ra{2,} # 至少2次 ra? # 非贪婪 # 锚点 r^start # 行首 rend$ # 行尾 r\bword\b # 单词边界 # 分组 r(\d)-(\d) # 捕获组 r(?:abc) # 非捕获组 r(?Pyear\d{4}) # 命名组四、分组与命名组python复制下载import re pattern re.compile( r(?Pyear\d{4})-(?Pmonth\d{2})-(?Pday\d{2}) ) m pattern.search(日期: 2024-01-15) print(m.group(year)) # 2024 print(m.groupdict()) # {year: 2024, month: 01, day: 15} # 反向引用 re.sub(r(\w)\s\1, r\1, hello hello world) # hello world五、前后向断言python复制下载# 前瞻匹配后面是...的位置 rfoo(?bar) # foo后面是bar rfoo(?!bar) # foo后面不是bar # 后顾匹配前面是... r(?foo)bar # bar前面是foo r(?!foo)bar # bar前面不是foo # 提取价格数字后面是元 re.findall(r\d(?元), 苹果5元香蕉3元) # [5, 3]注意Python后顾断言必须是固定长度。六、常用实战模式6.1 邮箱校验python复制下载EMAIL re.compile( r^[a-zA-Z0-9._%-][a-zA-Z0-9.-]\.[a-zA-Z]{2,}$ )6.2 URL提取python复制下载URL re.compile( rhttps?://[^\s\]|www\.[^\s\] )6.3 手机号中国大陆python复制下载PHONE re.compile(r^1[3-9]\d{9}$)6.4 日志解析python复制下载LOG re.compile( r(?Pip\d\.\d\.\d\.\d) r- - \[(?Ptime[^\]])\] r\(?Pmethod\w) (?Ppath\S) HTTP/[\d.]\ r(?Pstatus\d) (?Psize\d) )6.5 HTML标签清理python复制下载def strip_html(text): return re.sub(r[^], , text)6.6 驼峰与下划线转换python复制下载def camel_to_snake(name): return re.sub(r(?!^)(?[A-Z]), _, name).lower() def snake_to_camel(name): parts name.split(_) return parts[0] .join(p.capitalize() for p in parts[1:])七、性能优化7.1 避免灾难性回溯python复制下载# 危险嵌套量词 r(a)b # 输入 aaaaaaaaaaaaaaaaaaaaaac 会指数级回溯 # 优化原子组或占有量词 r(?a)b # Python 3.11 r(a)b # 占有量词7.2 优先字符类而非或python复制下载# 慢 r(cat|dog|bird) # 快 r(?:cat|dog|bird) # 至少用非捕获组7.3 用具体字符类替代.*python复制下载# 慢 rdiv.*/div # 快 rdiv[^]*/div7.4 合理使用re.DOTALL、re.MULTILINEpython复制下载re.compile(r^ERROR, re.MULTILINE) # ^匹配每行行首 re.compile(ra.b, re.DOTALL) # .匹配换行 re.compile(rabc, re.IGNORECASE) # 忽略大小写八、常见陷阱8.1 忘记原始字符串python复制下载# 错误\d被当作转义 re.search(\d, text) # 正确 re.search(r\d, text)8.2re.matchvsre.searchmatch从开头匹配search扫描整个字符串fullmatch必须完全匹配python复制下载re.match(r\d, abc123) # None re.search(r\d, abc123) # 匹配1238.3 贪婪 vs 非贪婪python复制下载re.findall(r.*, ab) # [ab] re.findall(r.*?, ab) # [a, b]8.4 中文字符python复制下载r[\u4e00-\u9fa5] # 中文字符范围九、实战日志分析器python复制下载import re from collections import Counter LOG_PATTERN re.compile( r(?Pip[\d.]).*? r\(?Pmethod\w) (?Ppath\S).*?\ r(?Pstatus\d{3}) ) def analyze(path): status_counter Counter() path_counter Counter() with open(path) as f: for line in f: m LOG_PATTERN.search(line) if not m: continue status_counter[m.group(status)] 1 path_counter[m.group(path)] 1 return { status: status_counter.most_common(10), top_paths: path_counter.most_common(10), }十、总结正则表达式强大但需要谨慎使用。记住预编译、原始字符串、具体字符类、避免嵌套量词。复杂解析任务HTML、JSON不要用正则用专用解析器。用regex库可支持更高级特性如可变长度后顾。