Python re.findall()不终止

Python re.findall()不终止,python,regex,Python,Regex,下面我有一个相当复杂的正则表达式,它似乎永远不会终止。这不是一个简单地花很长时间的问题——我已经等了几分钟,等待一个没有运气的答复 下面是一段重现问题的代码: import re link = re.compile(u'(?i)((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\((?:[^\s()<>]+|(?:\([^\s()<>]+\)))*\))+(?:\(

下面我有一个相当复杂的正则表达式,它似乎永远不会终止。这不是一个简单地花很长时间的问题——我已经等了几分钟,等待一个没有运气的答复

下面是一段重现问题的代码:

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)
如果从字符串的末尾剥去%D0%B5%D1%82,它将在10秒左右工作。随着字符串和匹配复杂度的增加,检查表达式条件所需的处理量呈指数级增加,CPU的峰值可能会一直增加到100%

这就是所谓的——在我看来,你有99到100个问题

CPU被阻塞,无法继续处理表达式

解决方案:

使用更可靠、更合理的选项简化您的表达,或者 在尝试验证之前缩短/截断样本有点违背了最初使用表达式的目的 我真的不知道这是否能帮你减少,但是因为你有很多重叠的条件,这似乎能减少它们。最好检查一组样本以验证:

(?i)(?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)((?:\(?[^\s()<>]+\)?)*[^\s`!()\[\]{};:\'".,<>?\xab\xbb\u201c\u201d\u2018\u2019])
例如:

我相信你可以简化它甚至更多,这只是一个快速尝试这样做。字符串上的处理时间:少于100ms。

如果从字符串末尾去掉%D0%B5%D1%82,则它可以工作,尽管只需10秒左右。随着字符串和匹配复杂度的增加,检查表达式条件所需的处理量呈指数级增加,CPU的峰值可能会一直增加到100%

这就是所谓的——在我看来,你有99到100个问题

CPU被阻塞,无法继续处理表达式

解决方案:

使用更可靠、更合理的选项简化您的表达,或者 在尝试验证之前缩短/截断样本有点违背了最初使用表达式的目的 我真的不知道这是否能帮你减少,但是因为你有很多重叠的条件,这似乎能减少它们。最好检查一组样本以验证:

(?i)(?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)((?:\(?[^\s()<>]+\)?)*[^\s`!()\[\]{};:\'".,<>?\xab\xbb\u201c\u201d\u2018\u2019])
例如:


我相信你可以简化它甚至更多,这只是一个快速尝试这样做。字符串的处理时间:小于100ms。

这可能不会有多大帮助。我不知道,但如果Python支持所有格量词,我不这么认为。 但如果它真的这样做了,下面的代码将阻止它灾难性的回溯。 我试着做一个等价物来阻止回溯而没有占有权。 是的,但意思变了,不匹配

您的正则表达式在每个细节上都是一个模拟的递归正则表达式。您可以在下面看到重复的模式。 这是这里的主要问题,因为它在本质上必须是所有格的,因为在现实中,它的匹配可选的平衡文本,没有边界来阻止它回溯

我认为在这种情况下,没有办法得到一个相等的非回溯正则表达式。 因此,如果不能使用所有格量词,正则表达式在任何上下文中都是注定要失败的

祝你好运! 注意:如果你使用,巨大的正则表达式是孩子们的游戏。这是一个剪切粘贴和按钮点击。修改它,压缩它,测试它。使用不同的构造重复多次


这可能帮不了什么忙。我不知道,但如果Python支持所有格量词,我不这么认为。 但如果它真的这样做了,下面的代码将阻止它灾难性的回溯。 我试着做一个等价物来阻止回溯而没有占有权。 是的,但意思变了,不匹配

您的正则表达式在每个细节上都是一个模拟的递归正则表达式。您可以在下面看到重复的模式。 这是这里的主要问题,因为它在本质上必须是所有格的,因为在现实中,它的匹配可选的平衡文本,没有边界来阻止它回溯

我认为在这种情况下,没有办法得到一个相等的非回溯正则表达式。 因此,如果不能使用所有格量词,正则表达式在任何上下文中都是注定要失败的

祝你好运! 注意:如果你使用,巨大的正则表达式是孩子们的游戏。这是一个剪切粘贴和按钮点击。修改它,压缩它,测试它。使用不同的构造重复多次


你试过re.findallink,text,flags=re.DEBUG吗?有一个灾难性的回溯这里有一个负的?谢谢你的可视化!我会把那个网站储存在我的书签里…@Madison May-Posseive quant's?嘿,我在下面给你留了个帖子。您的正则表达式是一个硬核的平衡文本递归模拟。它不能简化为等价物。它总是会导致灾难性的回溯。我想你会想知道的。你试过re.findallink,text,flags=re.DEBUG吗?有一个灾难性的回溯这里有一个负号?谢谢你的可视化!我会储存
那个网站在我的书签里…@Madison May-Posseive quant's?嘿,我在下面给你留了个帖子。您的正则表达式是一个硬核的平衡文本递归模拟。它不能简化为等价物。它总是会导致灾难性的回溯。我想你会想知道的。太棒了,谢谢你的回复。我做了更多的研究,证实了这是一个灾难性的回溯,所以在这一点上简化似乎是一个不错的选择。我使用这个regex-MacGruber的URL-regex是因为它看起来很标准,但出于我的目的,我认为简化一些事情是可以的。我也很欣赏regex测试URL。好东西!祝你好运。太棒了,谢谢你的回复。我做了更多的研究,证实了这是一个灾难性的回溯,所以在这一点上简化似乎是一个不错的选择。我使用这个regex-MacGruber的URL-regex是因为它看起来很标准,但出于我的目的,我认为简化一些事情是可以的。我也很欣赏regex测试URL。好东西!祝你好运。我最终的解决方案是删除正则表达式的平衡parens部分-但再次感谢链接和难以置信的详细答案。我最终的解决方案是删除正则表达式的平衡parens部分-但再次感谢链接和难以置信的详细答案。
 #  (?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]))

 #  matches:  'http://ru.wikipedia.org/wiki/%D0%9B%D0%BE%D0%B2%D0%B5%D1%86_%D1%81%D0%BD%D0%BE%D0%B2_'

 (?i)
 (
      (?:
           https?://
        |  www \d{0,3} [.] 
        |  [a-z0-9.\-]+ [.] [a-z]{2,4} /
      )
      (?:
           [^\s()<>]+ 
        |  \(
           (?:
                [^\s()<>]+ 
             |  (?: \( [^\s()<>]+ \) )
           )*+                           #  <- Possesive
           \)
      )+
      (?:
           \(
           (?:
                [^\s()<>]+ 
             |  (?: \( [^\s()<>]+ \) )
           )*+                           #  <- Possesive
           \)
        |  [^\s`!()\[\]{};:\'".,<>?\xab\xbb\u201c\u201d\u2018\u2019] 
      )
 )