我有一个用户提交的内容负载。它是HTML,可能包含URL。其中一些将是<a>
已经(如果用户是好的),但有时用户懒惰,只需键入www.something.com或最好http://www.something.com。需要一个很好的正则表达式来将URL转换为链接,但只保留现有链接
我找不到一个体面的正则表达式来捕获URL,但忽略立即在双引号或'>'右边的那些。任何人都有一个?
我有一个用户提交的内容负载。它是HTML,可能包含URL。其中一些将是<a>
已经(如果用户是好的),但有时用户懒惰,只需键入www.something.com或最好http://www.something.com。需要一个很好的正则表达式来将URL转换为链接,但只保留现有链接
我找不到一个体面的正则表达式来捕获URL,但忽略立即在双引号或'>'右边的那些。任何人都有一个?
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 ...
无耻插头:你可以看看这里(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参数,你不必触摸那个。
一旦你确认此做正确的事你大部分时间(与用户提供的数据,你永远无法确定),你可以做其余的两个步骤,正如我在另议它问题:
<a>
标签。<a>
标签,去掉最里面的一个要跳过现有的只使用一个向后看 - 添加(?<!href=")
到你的正则表达式的开始,所以它看起来是这样的:
/(?<!href=")http://\S*/
显然,这不是对找到所有类型的URL的完整的解决方案,但是这应该解决您与现有搞乱的问题。
我做了少许修改包含在原来的答案正则表达式:
(?<![.*">])\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”等
希望有所帮助。
这条线程比较古老,但我在处理自己的问题时遇到了它:也就是说,将任何网址转换为链接,但不要将任何已经存在于锚定标记中的网址留下。过了一会儿,这是什么弹出:
(?!(?!.*?<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>
只是想回贡献为了节省一些时间。
if (preg_match('/\b(?<!=")(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[A-Z0-9+&@#\/%=~_|](?!.*".*>)(?!.*<\/a>)/i', $subject)) {
# Successful match
} else {
# Match attempt failed
}
我刚开始添加的=在(?])不会打破link(不带引号的锚标记)。尼斯正则表达式顺便说一句:) – Joel 2010-06-29 10:41:41
@Joel:你确定你希望lookbehind意思是“断言在字符串中当前位置之前不可能匹配点,星号,引号或关闭角括号”吗? – 2012-04-13 16:44:16