下面我有一个相当复杂的正则表达式,它似乎永远不会终止。这不仅仅是花费很长时间的问题-我已经等了几分钟才没有运气。
下面是一些重现该问题的代码:
import re
link = re.compile(u'(?i)((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\((?:[^\s()<>]+|(?:\([^\s()<>]+\)))*\))+(?:\((?:[^\s()<>]+|(?:\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:\'".,<>?\xab\xbb\u201c\u201d\u2018\u2019]))', re.IGNORECASE)
text = "Check out this link http://ru.wikipedia.org/wiki/%D0%9B%D0%BE%D0%B2%D0%B5%D1%86_%D1%81%D0%BD%D0%BE%D0%B2_(%D0%B0%D0%BC%D1%83%D0%BB%D0%B5%D1%82"
matches = re.findall(link, text)
这是将re.DEBUG作为标志传递给模式的输出:
subpattern 1
subpattern None
branch
literal 104
literal 116
literal 116
literal 112
max_repeat 0 1
literal 115
literal 58
literal 47
literal 47
or
literal 119
literal 119
literal 119
max_repeat 0 3
in
category category_digit
literal 46
or
max_repeat 1 4294967295
in
range (97, 122)
range (48, 57)
literal 46
literal 45
literal 46
max_repeat 2 4
in
range (97, 122)
literal 47
max_repeat 1 4294967295
subpattern None
branch
max_repeat 1 4294967295
in
negate None
category category_space
literal 40
literal 41
literal 60
literal 62
or
literal 40
max_repeat 0 4294967295
subpattern None
branch
max_repeat 1 4294967295
in
negate None
category category_space
literal 40
literal 41
literal 60
literal 62
or
subpattern None
literal 40
max_repeat 1 4294967295
in
negate None
category category_space
literal 40
literal 41
literal 60
literal 62
literal 41
literal 41
subpattern None
branch
literal 40
max_repeat 0 4294967295
subpattern None
branch
max_repeat 1 4294967295
in
negate None
category category_space
literal 40
literal 41
literal 60
literal 62
or
subpattern None
literal 40
max_repeat 1 4294967295
in
negate None
category category_space
literal 40
literal 41
literal 60
literal 62
literal 41
literal 41
or
in
negate None
category category_space
literal 96
literal 33
literal 40
literal 41
literal 91
literal 93
literal 123
literal 125
literal 59
literal 58
literal 39
literal 34
literal 46
literal 44
literal 60
literal 62
literal 63
literal 171
literal 187
literal 8220
literal 8221
literal 8216
literal 8217
最佳答案
如果将%D0%B5%D1%82
去除字符串的末尾,它将起作用(尽管大约10s)。随着字符串和匹配项复杂度的增加,检查表达式条件所需的处理量呈指数增长,并且可能会将CPU的峰值消耗高达100%。
这称为catastrphic backtracking -在我看来,您遇到了99到100个问题;)
CPU被阻塞到无法继续处理表达式的地步。
解决方案:
简化您的表达方式(更可靠,更明智的选择),或者
在尝试验证样本之前先将其缩短/截断(这有点违反了使用表达式的目的)
老实说,我不知道这是否会帮您削减,但由于您有很多重叠的条件,因此看来可以减少它们。最好检查一堆样本以验证:
(?i)(?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)((?:\(?[^\s()<>]+\)?)*[^\s`!()\[\]{};:\'".,<>?\xab\xbb\u201c\u201d\u2018\u2019])
示例:http://regex101.com/r/lV0oL4
我相信您可以进一步简化它,但这只是一个快速的尝试。字符串的处理时间:少于100毫秒。
关于python - Python re.findall()不会终止,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21146406/