【问题标题】:Python regex freezes with small input stringPython 正则表达式冻结与小输入字符串
【发布时间】:2017-01-29 21:44:30
【问题描述】:

我在一堆维基百科页面上使用正则表达式。实际上对于第一个像 20 页的工作非常好,但是在我没有看到任何原因的情况下它突然冻结了。中断脚本提供了这个:

File "imageListFiller.py", line 30, in getImage
foundImage = re.search(urlRegex, str(decodedLine))
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/re.py",line 173, in search
return _compile(pattern, flags).search(string)

这是我的代码:

def getImage(wikiHtml):  
    urlRegex = """File:((?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:[0-9a-fA-F][0-9a-fA-F]))*?\.(png|jpg|svg|JPG))"""
uselessPictures = ("Wiktionary-logo-v2.svg", "Disambig_gray.svg",
                   "Question_book-new.svg", "Commons-logo.png")    

for line in wikiHtml:
    decodedLine = line.decode('utf-8')
    foundImage = re.search(urlRegex, str(decodedLine))
    if foundImage:
        if not foundImage.group(1) in uselessPictures:
            return foundImage.group(1)

这是导致它冻结的输入字符串:

href="/wiki/File:EARTH_-_WIKIPEDIA_SPOKEN_ARTICLE_(Part_01).ogg" title="收听这篇文章"> src="//upload.wikimedia.org/wikipedia/commons/thumb/4/47/Sound-icon .svg/20px-Sound-icon.svg.png" width="20" height="15" srcset="//upload.wikimedia.org/wikipedia/commons/thumb/4/47/Sound-icon.svg/ 30px-Sound-icon.svg.png 1.5x, //upload.wikimedia.org/wikipedia/commons/thumb/4/47/Sound-icon.svg/40px-Sound-icon.svg.png 2x" 数据文件-width="128" 数据文件高度="96" > />

正则表达式实际上不应该在这里匹配,它只需要跳过这一行。 谢谢!

【问题讨论】:

  • 仅供参考:请注意,[$-_] 匹配所有大写 ASCII 字母和数字等。如果你避开连字符,它已经安全得多了。
  • 你(或更好的表达方式)容易发生灾难性的回溯:regex101.com/r/eH4nJ2/1
  • 为什么不简单地([^/]*\.(png|jpg|svg|JPG))

标签: python regex freeze


【解决方案1】:

模式中的$-_ 部分创建了一个匹配大写字母和数字,甚至更多字符的范围。由于组中的其他替代分支可能会在同一位置匹配(例如 [a-zA-Z]),从而导致超时/灾难性回溯问题。

您只需连接所有仅匹配第一组中 1 个字符的字符类,然后转义字符类中的 - 或将其放在字符类的开始/结束处(我仍然如果将来要更新模式,请转义它):

r"""File:((?:[0-9a-fA-F]{2}|[a-zA-Z0-9\-$_@.&+!*(),])*?\.(png|jpg|svg|JPG))"""

请参阅regex demo

此外,较长的替代方案应先于较短的替代方案,因此 [0-9a-fA-F]{2} 应先出现。

另外,\w 可用于稍微缩短模式(替换[a-zA-Z0-9_]):

r"""File:((?:[0-9a-fA-F]{2}|[\w\-$@.&+!*(),])*?\.(png|jpg|svg|JPG))"""
                             ^^^  

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-18
    • 1970-01-01
    • 2015-07-13
    • 1970-01-01
    相关资源
    最近更新 更多