我最近为问题" A Regex that will never be matched by anything"定了一堆正则表达式。 (my answer here,请参阅更多信息)。
但是,经过我的测试后,我注意到正则表达式select tasker_id, min(sum_worked) as min_worked from (
select tasker_id, sum(working_hours) as sum_worked
from test.test
group by tasker_id
having sum_worked>0)a
;
和'a^'
需要花费大量不同的时间来检查,尽管它们应该完全相同。 (这只是偶然的,我甚至改变了角色。)这些时间在下面。
'x^'
在线测试(仅前50行)显示相同的行为(1441880步和~710ms,仅40858步和~113ms):https://regex101.com/r/AwaHmK/1
Python在这里做什么使In [1]: import re
In [2]: with open('/tmp/longfile.txt') as f:
...: longfile = f.read()
...:
In [3]: len(re.findall('\n',longfile))
Out[3]: 275000
In [4]: len(longfile)
Out[4]: 24733175
...
In [45]: %timeit re.search('x^',longfile)
6.89 ms ± 31.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [46]: %timeit re.search('a^',longfile)
37.2 ms ± 739 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [47]: %timeit re.search(' ^',longfile)
49.8 ms ± 844 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
比'a^'
花费的时间长得多?
为了看看'x^'
或IPython中是否有某些内容,我自己写了一个简单的计时功能,所有内容都检查出来:
timeit
我还在IPython之外的标准In [57]: import time
In [59]: import numpy as np
In [62]: def timing(regex,N=7,n=100):
...: tN = []
...: for i in range(N):
...: t0 = time.time()
...: for j in range(n):
...: re.search(regex,longfile)
...: t1 = time.time()
...: tN.append((t1-t0)/n)
...: return np.mean(tN)*1000, np.std(tN)*1000
...:
In [63]: timing('a^')
Out[63]: (37.414282049451558, 0.33898056279589844)
In [64]: timing('x^')
Out[64]: (7.2061508042471756, 0.22062989840321218)
shell中复制了我的结果。所以奇怪的是不受限于IPython或3.5.2
。
答案 0 :(得分:4)
如链接问题中所述,此正则表达式扫描整个文本。
这里看到的时间差异仅仅是因为“a”是英文文本中的常见字母,并且您使用了可读数据。因此,如果你研究正则表达式引擎是如何工作的,你会理解:使用模式a^
导致更多的延迟,因为在第一个“a”上找到了暂定的匹配,然后被拒绝。引擎有两个“读头”,它们都从左向右移动 - 一个在字符串中移动,另一个在正则表达式中移动。将a^
模式与您选择的人类可读数据结合使用,正则表达式引擎必须完成更多工作。由于“x”是语料库中不常见的字母,因此使用模式x^
会浪费更少的时间 - 文本中的更多位置可以立即被拒绝。
e^
甚至会比a^
慢,因为“e”更频繁出现在英文中。)a^
和x^
模式的执行方式类似。总之,考虑到正则表达式引擎的内部工作原理和所选测试数据的更广泛背景,这两个“等效”永不匹配的正则表达式模式a^
和x^
实际上并非如此等效