我一直在研究这个问题,只找到了两个相关的答案,但一直都不起作用。
无论如何。我试图在文本中找到链接并自动链接,如果它们已经在html标记中,则不自动链接。(<a><img>),并且它必须支持所有链接,如http、https和www
我对regex很反感,但我试着把一些东西组合在一起。
function b($text)
{
// a more readably-formatted version of the pattern is on http://daringfireball.net/2010/07/improved_regex_for_matching_urls
$pattern = '(?i)'b((?:[a-z]['w-]+:(?:/{1,3}|[a-z0-9%])|www'd{0,3}[.]|[a-z0-9.'-]+[.][a-z]{2,4}/)(?:[^'s()<>]+|'(([^'s()<>]+|('([^'s()<>]+')))*'))+(?:'(([^'s()<>]+|('([^'s()<>]+')))*')|[^'s`!()'[']{};:''".,<>?«»“”‘’]))';
$callback = create_function('$matches', '
$url = array_shift($matches);
$url_parts = parse_url($url);
$text = parse_url($url, PHP_URL_HOST) . parse_url($url, PHP_URL_PATH);
$text = preg_replace("/^www./", "", $text);
$last = -(strlen(strrchr($text, "/"))) + 1;
if ($last < 0) {
$text = substr($text, 0, $last) . "…";
}
return "<a rel="nofollow" href=".$url.">".$text."</a>";
');
return preg_replace_callback($pattern, $callback, $text);
}
function autolink($txt)
{
return preg_replace_callback('#(?<!href'=[''"])(https?|ftp|file)://[-A-Za-z0-9+&@'#/%()?=~_|$!:,.;]*[-A-Za-z0-9+&@'#/%()=~_|$]#', 'b', $txt);
}
但运气不好,我现在不知道该怎么办。
您需要某种HTML解析器才能使其完美工作。请记住,还有其他标签/语法可以包含URL,如<script>
、<style>
、注释等。
如果一个简单的正则表达式解决方案解决了问题中的问题就足够了,那么您可以使用以下内容:
function linkify($input){
$re = <<<'REGEX'
!
(
<'w++
(?:
's++
| [^"'<>]++
| "[^"]*+"
| '[^']*+'
)*+
>
)
|
('b https?://[^'s"'<>]++ )
|
('b www'd*+'.'w++[^'s"'<>]++ )
!xi
REGEX;
return preg_replace_callback($re, function($m){
if($m[1]) return $m[1];
$url = htmlspecialchars($m[2] ? $m[2] : "http://$m[3]");
$text = htmlspecialchars("$m[2]$m[3]");
return "<a rel='nofollow' href='$url'>$text</a>";
},
$input);
}
第一个捕获组与HTML标记匹配。如果定义了第一个捕获组(未更改的HTML标记),则该表达式将替换为它,否则将替换为指向第二个或第三个捕获组的链接。
演示:输入:
<img src='http://foo'>www.test.com/?x&y
输出:
<img src='http://foo'><a rel='nofollow' href='http://www.test.com/?x&y'>www.test.com/?x&y</a>