2008-11-13 88 views

回答

14

Jan Goyvaerts,RegexBuddy的创建者,拥有written a response给Jeff Atwood的博客,该博客解决Jeff提供的问题并提供了一个很好的解决方案。

\b(?:(?:https?|ftp|file)://|www\.|ftp\.)[-A-Z0-9+&@#/%=~_|$?!:,.]*[A-Z0-9+&@#/%=~_|$] 

为了忽略发生的旁边的一个“或>,您可以添加(?<![">])的正则表达式的开始比赛,所以你得到

(?<![">])\b(?:(?:https?|ftp|file)://|www\.|ftp\.)[-A-Z0-9+&@#/%=~_|$?!:,.]*[A-Z0-9+&@#/%=~_|$] 

这将匹配完整地址(http://.. )以及与WWW或FTP起始地址 - 你的运气与地址一样ars.userfriendly.org ...

0

无耻插头:你可以看看这里(regular expression replace a word by a link)为灵感

这个问题要求用某个链接替换某个词,除非已经存在链接。所以你遇到的问题或多或少是一回事。

您只需要一个匹配URL的正则表达式(代替单词)。最简单的假设是这样的:一个URL(可选)以"http://","ftp://""mailto:"开头,只要没有空格字符,换行符,标记括号或引号就可以持续。

要小心,长的正则表达式在前面。不区分大小写应用。

(href\s*=\s*['"]?)?((?:http://|ftp://|mailto:)?[^.,<>"'\s\r\n\t]+(?:\.(?![.<>"'\s\r\n])[^.,!<>"'\s\r\n\t]+)+) 

被警告 - 这也将匹配在技术上无效的网址,它可以识别things.formatted.like.this作为URL。如果它太不灵敏,这取决于你的数据。如果你有例子返回误报,我可以微调正则表达式。

正则表达式将产生两个匹配组。第2组将包含匹配的东西,这很可能是一个URL。组1将包含一个空字符串或'href="'。你可以用它作为一个指标,表明这个匹配发生在里面现有链接的href参数,你不必触摸那个。

一旦你确认此做正确的事你大部分时间(与用户提供的数据,你永远无法确定),你可以做其余的两个步骤,正如我在另议它问题:

  1. 让周围的每一个URL链接存在(除非有东西在比赛第1组!)这产生的事物,本来就有连杆双嵌套<a>标签。
  2. 扫描错误嵌套<a>标签,去掉最里面的一个
0

要跳过现有的只使用一个向后看 - 添加(?<!href=")到你的正则表达式的开始,所以它看起来是这样的:

/(?<!href=")http://\S*/ 

显然,这不是对找到所有类型的URL的完整的解决方案,但是这应该解决您与现有搞乱的问题。

10

我做了少许修改包含在原来的答案正则表达式:

(?<![.*">])\b(?:(?:https?|ftp|file)://|[a-z]\.)[-A-Z0-9+&#/%=~_|$?!:,.]*[A-Z0-9+&#/%=~_|$] 

,让更多的子域,并可以运行在标签更为全面检查。若要将此PHP的预浸料代替,你可以使用:

$convertedText = preg_replace('@(?<![.*">])\b(?:(?:https?|ftp|file)://|[a-z]\.)[-A-Z0-9+&#/%=~_|$?!:,.]*[A-Z0-9+&#/%=~_|$]@i', '<a href="\0" target="_blank">\0</a>', $originalText); 

注意,我删除@从正则表达式,为了使用它作为一个的preg_replace分隔符。无论如何,@将很少用在URL中。

很明显,你可以修改替换文本,并删除目标=“_空白”,或添加相对=“nofollow”等

希望有所帮助。

+0

我刚开始添加的=在(?])不会打破link(不带引号的锚标记)。尼斯正则表达式顺便说一句:) – Joel 2010-06-29 10:41:41

+0

@Joel:你确定你希望lookbehind意思是“断言在字符串中当前位置之前不可能匹配点,星号,引号或关闭角括号”吗? – 2012-04-13 16:44:16

11

这条线程比较古老,但我在处理自己的问题时遇到了它:也就是说,将任何网址转换为链接,但不要将任何已经存在于锚定标记中的网址留下。过了一会儿,这是什么弹出:

(?!(?!.*?<a)[^<]*<\/a>)(?:(?:https?|ftp|file)://|www\.|ftp\.)[-A-Z0-9+&#/%=~_|$?!:,.]*[A-Z0-9+&#/%=~_|$] 

用下面的输入:

http://www.google.com 
http://google.com 
www.google.com 

<p>http://www.google.com<p> 

this is a normal sentence. let's hope it's ok. 

<a href="http://www.google.com">www.google.com</a> 

这是一个preg_replace函数的输出:

<a href="http://www.google.com" rel="nofollow">http://www.google.com</a> 
<a href="http://google.com" rel="nofollow">http://google.com</a> 
<a href="www.google.com" rel="nofollow">www.google.com</a> 

<p><a href="http://www.google.com" rel="nofollow">http://www.google.com</a><p> 

this is a normal sentence. let's hope it's ok. 

<a href="http://www.google.com">www.google.com</a> 

只是想回贡献为了节省一些时间。

1
if (preg_match('/\b(?<!=")(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[A-Z0-9+&@#\/%=~_|](?!.*".*>)(?!.*<\/a>)/i', $subject)) { 
    # Successful match 
} else { 
    # Match attempt failed 
}