点击头像,进入个人中心,查看文章合集,还有更多Python相关的精彩教程等着你![灵光一闪]
(图片来源网络,侵删)
在前几章,我们学习了正则的各种语法与应用。本章我们要解决一个实际问题:当数据量很大时,如何让正则 运行得更快?
7.1 为什么要编译正则?每次调用 re.match() / re.search() 等方法时:
Python 内部会先解析正则表达式然后再执行匹配如果同一个正则要多次使用,频繁解析会浪费性能。
✅ 解决办法:使用 re.compile() 先编译一次,后续重复使用。
7.2 基本用法:re.compile()import repattern = re.compile(r"\d{4}-\d{2}-\d{2}") # 编译正则dates = ["2025-09-05", "1999-01-01", "hello"]for d in dates: if pattern.match(d): print("合法日期:", d)输出:
合法日期: 2025-09-05合法日期: 1999-01-017.3 提升性能的技巧技巧 1:预编译正则如果在循环里重复用同一个正则,一定要 compile。
import repattern = re.compile(r"\d+")numbers = ["abc123", "456xyz", "no_digits"]for s in numbers: if pattern.search(s): print("找到数字:", s)技巧 2:避免低效的模式一些写法会拖慢速度:
低效写法
高效写法
原因
.*a
[^a]*a
.* 会疯狂回溯
`(a
b
c
(abc)*
(?:abc)*
非捕获组更轻量
技巧 3:使用非捕获分组 (?: … )如果只是为了分组,而不需要捕获结果,推荐用 非捕获分组。
import re# 捕获分组(多余)pattern1 = re.compile(r"(?:ab|cd)+") pattern2 = re.compile(r"(ab|cd)+") # 性能略差print(pattern1.match("abcdab")) # <re.Match ...>技巧 4:控制回溯正则引擎会“试探性回溯”,在复杂表达式里可能非常慢。常见优化方法:
避免 .* 这种“贪婪全局”匹配用 ? 变为非贪婪尽量用明确的量词 {m,n}7.4 使用 finditer() 处理大文本findall() 会一次性返回所有结果,可能很占内存。推荐用 finditer():返回一个迭代器,每次取一个匹配。
import retext = "number: " + "123 " * 100000pattern = re.compile(r"\d+")count = 0for m in pattern.finditer(text): count += 1print("匹配次数:", count)输出:
匹配次数: 1000007.5 使用 fullmatch() 替代 ^...$很多人会写:
re.match(r"^\d+$", "123")其实更推荐:
re.fullmatch(r"\d+", "123")这样更直观,也能避免错误。
7.6 图示:编译与回溯假设正则:a.*b字符串:accccccccccccb
匹配过程:
a cccccccccccb^ ^从头到尾匹配,.* 会不断尝试回溯,直到遇到 b如果写成 a[^b]*b,则一次性就能匹配成功。
7.7 小练习请写正则并优化:
判断一个字符串是否是合法的 IPv4 地址(例如 192.168.0.1)。提取字符串 "color: #FFEEAA; background: #123456;" 中所有 十六进制颜色代码。从超长日志中提取所有日期(格式 YYYY-MM-DD),要求内存占用尽量小。✅ 本章你学到了:
使用 re.compile() 预编译正则优化正则性能的方法(避免回溯、非捕获分组、字符类优化)大数据处理时推荐 finditer()fullmatch() 更直观替代 ^...$下一章(第 8 章),我们会进入 正则表达式的实战案例:日志分析、数据提取、文本清洗等。
转载请注明来自海坡下载,本文标题:《编译的速度优化(Python 正则表达式教程 第 7 章编译与性能优化)》
京公网安备11000000000001号
京ICP备11000001号
还没有评论,来说两句吧...