Python中如何优化这个正则表达式?
下面这个正则:
re.findall(r’(?<!数量)\d+’,‘数量 123 单价 45 金额 5535’)
得到了结果:
[‘23’, ‘45’, ‘5535’]
我想以否定的模式来写,就是不想提取数量后面的数值,在结果的 list 里面数量那个 23 不应该出现的。
Python中如何优化这个正则表达式?
自己研究写了一个出来。python 3
re.findall(r’[一-龥]+(?<!数量)(\d+)’,‘数量 123 单价 45 金额 5535’)
结果:
[‘45’, ‘5535’]
帖子标题没给出具体的正则表达式,所以没法直接优化。不过,哥们儿,正则表达式优化通常就那几招,我给你列个通用思路,你对着自己的表达式看看。
核心优化策略:
- 避免灾难性回溯:这是性能杀手。检查你的表达式里有没有
(.*)*、(a+)+这种嵌套的量词(*,+,?,{m,n})。有的话,尽量用更精确的匹配(比如[^"]*代替.*?)或者用原子分组(?>...)来防止回溯。 - 使用非贪婪匹配要小心:
.*?看起来省事,但引擎会尝试很多次“最短匹配”。如果上下文明确,用[^x]*(匹配直到字符x)这种否定字符集通常更快。 - 编译重用:如果你在一个循环或多次调用里用同一个模式,一定要用
re.compile()预编译它。 - 具体化你的模式:越具体越好。用
\d代替[0-9](其实一样),用[A-Za-z]代替.*来匹配字母。 - 使用
re.VERBOSE:写复杂的表达式时,用它加注释和换行,虽然不影响性能,但能让你自己看懂,便于维护和优化。 - 考虑不用正则:如果匹配需求很简单(比如固定字符串、前缀、后缀),直接用
str.find(),str.startswith(),str.endswith(),它们快得多。 - 用
re.search()代替re.match():如果你不是非得从字符串开头匹配,re.search()更灵活。但注意,re.match()只在开头匹配,有时更快。
举个简单例子:
假设你想匹配引号内的内容,原表达式可能是 "(.+?)"。优化的话,可以改成 "([^"]*)"。后者用否定字符集 [^"] 直接匹配到下一个引号,避免了非贪婪 ? 的反复尝试。
代码示例(编译和具体化):
import re
# 不好的做法:在循环里重复编译
for text in text_list:
match = re.search(r'\d{4}-\d{2}-\d{2}', text) # 每次循环都编译
# 好的做法:预编译
date_pattern = re.compile(r'\d{4}-\d{2}-\d{2}')
for text in text_list:
match = date_pattern.search(text) # 用编译好的对象
一句话建议: 具体化模式、避免回溯、预编译重用。
因为匹配了 “数量 1 ”
re.findall(r’(?<!数量)\s(\d+)’,‘数量 123 单价 45 金额 5535’)
嗯,非常感谢大大
数量和\d 中间加个空格试试
其实字符串之间没有空格,我那个还是能起作用
(?<!数量\d*)\d+
空格是 V2 后台加的么?
python 的 re.findall 总有难以预想的情况
正常理解,「(?<!数量)\d+」和「(?<!数量)(\d+)」是一样的,似乎 python 里面有优先级的区别
你这个报错。提示 look-behind requires fixed-width pattern
编译器的锅好像,不支持不定长度。(?<!数量[0-9]{0,100000})[0-9]+这样就可以了


