您的代码在 iframe 等中应该不是什么大问题,因为在那里您"
的 URL 前面通常有一个,而不是您的模式需要的空格。
但是,这里有不同的解决方案。<
如果您有单个或>
在 HTML 注释或类似内容中,它可能无法 100% 工作。但在任何其他情况下,它应该为您提供良好的服务(我不知道这是否对您来说是个问题)。它使用负前瞻来确保>
在任何打开之前没有关闭<
(因为这意味着您在标签内)。
$content = preg_replace('$(\s|^)(https?://[a-z0-9_./?=&-]+)(?![^<>]*>)$i', ' <a href="$2" target="_blank">$2</a> ', $content." ");
$content = preg_replace('$(\s|^)(www\.[a-z0-9_./?=&-]+)(?![^<>]*>)$i', '<a target="_blank" href="http://$2" target="_blank">$2</a> ', $content." ");
如果您不熟悉这种技术,这里有一些详细说明。
(?! # starts the lookahead assertion; now your pattern will only match, if this subpattern does not match
[^<>] # any character that is neither < nor >; the > is not strictly necessary but might help for optimization
* # arbitrary many of those characters (but in a row; so not a single < or > in between)
> # the closing >
) # ends the lookahead subpattern
请注意,我更改了正则表达式分隔符,因为我现在!
在正则表达式中使用。
(\s|^)
除非您还需要标签之外的 URL的第一个子模式,您现在也可以删除它(并减少替换中的捕获变量)。
$content = preg_replace('$(https?://[a-z0-9_./?=&-]+)(?![^<>]*>)$i', ' <a href="$1" target="_blank">$1</a> ', $content." ");
$content = preg_replace('$(www\.[a-z0-9_./?=&-]+)(?![^<>]*>)$i', '<a target="_blank" href="http://$1" target="_blank">$1</a> ', $content." ");
最后......您是否打算不替换最后包含锚点的 URL?例如www.hello.com/index.html#section1
?如果您不小心错过了这个,请添加#
到您允许的 URL 字符中:
$content = preg_replace('$(https?://[a-z0-9_./?=&#-]+)(?![^<>]*>)$i', ' <a href="$1" target="_blank">$1</a> ', $content." ");
$content = preg_replace('$(www\.[a-z0-9_./?=&#-]+)(?![^<>]*>)$i', '<a target="_blank" href="http://$1" target="_blank">$1</a> ', $content." ");
编辑:另外,+
and%
呢?还有一些其他字符可以在不编码的情况下出现在 URL 中。看到这个。 编辑结束
我认为这应该对你有用。但是,如果您可以提供一个显示有效和损坏的 URL 的示例(使用您拥有的代码),我们实际上可以提供经过测试适用于您的所有案例的解决方案。
最后一个想法。正确的解决方案是使用 DOM 解析器。然后你可以简单地将你已经拥有的正则表达式应用于文本节点。但是,您对 HTML 结构的关注非常有限,这使您的问题再次成为常态(只要您在 HTML 注释或页面上的 JavaScript 或 CSS 中没有不匹配的 '<' 或 '>')。如果你确实有这些特殊情况,你真的应该研究一下 DOM 解析器。在这种情况下,这里(到目前为止)提供的解决方案都不是安全的。