URL正则表达式奇怪的行为

时间:2015-04-15 12:50:37

标签: php regex url

我有一个用于使用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

或删除最后一封信&#39; n&#39;:

http://google.com(JavaScript_Add-o) //This is a match

或删除单词&#39;添加&#39;:

http://google.com(JavaScript_-on) //This is a match

有谁知道这里发生了什么以及如何解决这个问题?

2 个答案:

答案 0 :(得分:0)

使用延迟匹配。

只需将?添加到(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+?即可节省大量计算资源。我还加了一个?在下一个非捕获组中。这是一个更新版本:

(?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`!()\[\]{};:\'".,<>?«»“”‘’])
)

请参阅demo

答案 1 :(得分:0)

这应该可以正常工作: /(http [s]?:// | www。)\ w [^ \ s |&lt; \ ^ |(] + / gim;