我一直在研究这个问题,只找到了2个相关的答案,但仍然无法完成。
反正。我正在尝试在文本中找到链接并自动链接它们,如果它们已经在html标记中,则不会自动链接它们。 (< a>< img>)并且它必须支持所有链接,如http,https和www
我对正则表达式很可怕,但我试图把东西放在一起。
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);
}
但没有运气,我不知道该做什么。
答案 0 :(得分:5)
您需要某种HTML解析器才能使其完美运行。请记住,还有其他标记/语法可以包含网址,例如<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标记),则表达式将替换为第一个捕获组,否则将链接到第二个或第三个捕获组。
Demo :输入:
<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>