【发布时间】:2015-04-15 12:50:36
【问题描述】:
我有一个用于用 PHP 识别 URL 的正则表达式,效果很好:
~(?i)\b(?!.*?\<<)(?!.*?\.onion)((?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|ftp://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:\'".,<>?«»“”‘’]))~
除非这会破坏它,否则会导致灾难性的回溯:
http://google.com(JavaScript_Add-on)
有趣的是,这可以通过删除括号、下划线或连字符来避免:
http://google.comJavaScript_Add-on //This is a match
http://google.com(JavaScriptAdd-on) //This is a match
http://google.com(JavaScript_Addon) //This is a match
或者去掉最后一个字母'n':
http://google.com(JavaScript_Add-o) //This is a match
或删除“添加”一词:
http://google.com(JavaScript_-on) //This is a match
有谁知道这里发生了什么以及如何解决这个问题?
【问题讨论】:
-
括号和下划线不是有效的域名字符:因此它们都不是有效的 URL。
-
请在regex101.com/r/cI5eT2/2查看您修改后的正则表达式。只需将
?与(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+?相加即可节省大量计算资源。我还在下一个非捕获组中添加了?。答案:使用 lazy 匹配。