我有一个字符串
aaaa bbbb cccc=v1
我要捕获cccc = v1(field_value对,而不是确切的“ cccc”)。
为了提高性能,我使用了原子组,以便在找不到=
时不浪费时间回溯
\b[^\s=]++=\w+
但是发生的事情是即使它没有回溯,它也会像下面那样检查字符串中的每个字符
aaaa bbbb cccc=v1
^
aaaa bbbb cccc=v1
^
aaaa bbbb cccc=v1
^
aaaa bbbb cccc=v1
^
在这种情况下,当未捕获原子组时,我可以跳过匹配吗? 像这样
aaaa bbbb cccc=v1
^
aaaa bbbb cccc=v1
^
aaaa bbbb cccc=v1
^
我认为它绝对可以提高性能。
答案 0 :(得分:2)
一次匹配一个非=
单词中所有字符的 all 的一个选项是在模式的开头使用(?:\w+ )*
。 (如果不能保证=
单词,请使其占有所有,以防止回溯。)然后,使用\K
忘记先前匹配的文本,然后将=
单词与{{ 1}}:
[^\s=]++=\w+
https://regex101.com/r/RVogoh/5
尽管如此,当要搜索的整个字符串较小时-与原始字符串相比,只有63个步长,这只是适度的改进
https://regex101.com/r/RVogoh/1/
需要90步。仅当有许多字符时,此实现才比原始的逐字符测试显着提高效率。
请注意,^(?:\w+ )*+\K[^\s=]+=\w+
模块不支持\K
-为此,您必须使用pypi的re
模块。
答案 1 :(得分:0)
已更新
我认为您会发现,在行尾找到key=value
对时,大部分明智的正则表达式将具有合理的性能。 (即使是长行和部分匹配。)
以下是一些时间安排。我使用了this SO post中的cmpthese
函数来比较相对计时:
import re
import regex
def f1():
# re from my comment
return re.findall(r'(?<=[ ])(\w+=\w+)$', txt, flags=re.M)
def f2():
# the OP's regex
return regex.findall(r'\b([^\s=]++=\w+)', txt, flags=re.M)
def f3():
# alternate regex
return re.findall(r'(\w+=\w+)$', txt, flags=re.M)
def f4():
# CertainPerformance updated regex
return regex.findall(r'^(?:\w+ )*+\K[^\s=]+=\w+', txt, flags=regex.M)
def f5():
return [line.split()[-1] for line in txt.splitlines() if re.match(r'^(\w+=\w+)$', line.split()[-1])]
txt='''\
a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a bc d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d a b c d e=
aaaa bbbb cccc=v1
aaaa bbbb cccc
aaaa bbbb cccc=v1
'''*1000000
cmpthese([f1,f2,f3,f4,f5],c=3)
此代码在Python 2上打印(最慢显示在顶部,最快显示在底部):
rate/sec usec/pass f2 f4 f1 f3 f5
f2 0 36721115.669 -- -27.2% -72.0% -72.0% -77.5%
f4 0 26715482.632 37.5% -- -61.4% -61.5% -69.0%
f1 0 10300210.953 256.5% 159.4% -- -0.0% -19.6%
f3 0 10296802.362 256.6% 159.5% 0.0% -- -19.6%
f5 0 8280366.262 343.5% 222.6% 24.4% 24.4% --
和Python 3:
rate/sec usec/pass f2 f4 f3 f1 f5
f2 0 40880883.330 -- -42.3% -64.4% -70.3% -78.3%
f4 0 23592684.768 73.3% -- -38.4% -48.6% -62.3%
f3 0 14544536.920 181.1% 62.2% -- -16.6% -38.9%
f1 0 12131648.781 237.0% 94.5% 19.9% -- -26.7%
f5 0 8888514.997 359.9% 165.4% 63.6% 36.5% --
我相信f2
和f4
的慢速性更可能是通过使用regex
模块而不是re
模块来实现的,但是这些函数中的正则表达式需要使用{{ 1}}模块。苹果与苹果比较之下,regex
中的正则表达式应该很快。
您可以看到,使用f4
模块,在锚点后面稍微添加外观可以提高速度。 re
模块很可能是regex
比其他模块慢的罪魁祸首。从理论上讲,例如f4
中的正则表达式更快。</ p>
注释和“性能评估”仅关注regex101中的“步骤”数。这是不同正则表达式表达的相对性能的不完整描述。 Regex101在完成正则表达式所需的时间上也具有Perl
等级-这取决于服务器的土地。某些正则表达式步骤比其他步骤更快。
考虑正则表达式ms
在regex101 in this example中,运行它需要205个步骤和约2ms。
现在考虑(?<=[ ])
的{{3}},它需要83个步骤,但要运行大约2ms。
现在考虑使用[ \t]
中的更多simpler regex,尽管它需要405步,但运行时间却延长了将近5倍。
尽管(\w+)\1\b
是正则表达式速度的指标,但并不是每个步骤都花费相同的时间来执行。您还需要查看总执行时间。