正则表达式中的Python无限循环以匹配u

2024-04-19 02:39:16 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图从文本文件中提取url,并陷入无限循环

import re

URL_PATTERN = re.compile(ur'''(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))''')

with open("some_text_file") as RAW:
    for line in RAW:
        RESULT = URL_PATTERN.findall(line)
        links = []
        for HTTP_TUPLES in RESULT:
            links.append(HTTP_TUPLES[0])

我怎么才能避免呢?在

PS:是的,我知道urllib和其他模块


Tags: inimportrehttpurlforrawline
3条回答
(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>'",]+|\(([^\s()<>'",]+|(\([^\s()<>'",]+\)))*\))+(?:\(([^\s()<>'",]+|(\([^\s()<>'",]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))

试试看这个。这个会这样做的你。看到了吗演示。在

https://www.regex101.com/r/bC8aZ4/20

我不想在这个答案中说明正则表达式的正确性。您可能需要查看一下有关URL验证的this article,并为您的匹配任务自定义它。

问题

您的regex以(A*)*的形式包含灾难性回溯的经典示例。在

例如,在这一部分:

(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+

如果扔掉第二个分支,您将立即看到问题:

^{pr2}$

第二个分支还包含问题模式的实例:

([^\s()<>]+|(\([^\s()<>]+\)))*

退化为:

([^\s()<>]+)*

要演示此问题,可以在此不匹配的字符串上测试正则表达式:

sdfsdf http://www/sdfsdfsdf(sdsdfsdfsdfsdfsdfsdf sfsdf(Sdfsdf)(sdfsdF)(sdfdsF)(<))sdsdfsf

Demo on regex101

解决方案

使用上面的regex片段演示:

(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+
            ^             ^

在支持所有格量词的语言中,由于正则表达式的两个分支是互斥的,因此可以选择将这些量词设为所有格。在

但是,由于Python不支持所有格量词,您可以在不影响结果的情况下删除标记位置的限定符,因为它已经由最外层的限定符处理。在

最终结果(处理最后一组的相同问题):

(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]|\(([^\s()<>]|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))

Demo on regex101

尝试:

import re

URL_PATTERN = re.compile(ur'''(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))''')

RESULT = []
with open("some_text_file") as RAW:
  map(lambda x:RESULT.extend(URL_PATTERN.findall(x)), RAW.xreadlines())

在python3中,删除xreadlines(),因为file对象本身是一个迭代器。在

相关问题 更多 >