php 检测链接时regexp出错

drnojrws  于 2023-03-07  发布在  PHP
关注(0)|答案(2)|浏览(197)

我正在使用xampp测试我的网站,使用正则表达式检测链接并将它们转换为可单击格式,但当用户输入www.example.com而不是https://www.google.com时,链接将重定向到localhost/www.google.comwww.google.com instead of https://www.google.com the link redirects to localhost/www.google.com
我的代码

function link_detect($text){

  $ex = "/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[\-;:&=\+\$,\w]+@)?[A-Za-z0-9\.\-]+|(?:www\.|[\-;:&=\+\$,\w]+@)[A-Za-z0-9\.\-]+)((?:\/[\+~%\/\.\w\-_]*)?\??(?:[\-\+=&;%@\.\w_]*)#?(?:[\.\!\/\\\w]*))?)/i";
  return preg_replace($ex,'<a class="click_link" href="$1" target="_blank">$1</a>', $text);
}
vxf3dgd4

vxf3dgd41#

实际上,这与正则表达式无关,更多的是与链接有关。
在锚点中,浏览器知道链接指向互联网上 * 别处 * 的站点的唯一方法是提供URIhttp://表示URI(使用http方案)。
记住,在大多数文件系统中,一个文件可以有多个点,所以当你说 *go to www.google.com * 时,浏览器会认为你想去的是一个名为www,扩展名为.google.com的文件,它和foo.tar.gz没有什么不同。
如果有的话,只需要在URL前面加上一个//,在浏览器中,这意味着 * 在URL前面加上这个页面的任何协议/方案(http/https/file),并将其视为外部链接 *。

将其转换为Regex

一种可能的解决方案是尝试检测(((https?|file):)?\/\/)?,从中提取第4组(https?|file,它将找到httphttpsfile),然后将其预先挂在链接的开头,始终提供//
这样,如果没有指定方案,链接仍然会告诉浏览器使用默认方案,无论当前页面使用什么 *,并且 * 链接是 * 外部 *。
((((?:([A-Za-z]{3,9}):)?(?:\/\/)?)(?:[\-;:&=\+\$,\w]+@)?[A-Za-z0-9\.\-]+|(?:www\.|[\-;:&=\+\$,\w]+@)[A-Za-z0-9\.\-]+)((?:\/[\+~%\/\.\w\-_]*)?\??(?:[\-\+=&;%@\.\w_]*)#?(?:[\.\!\/\\\w]*))?)
4现在拥有协议(即http:)。将其中的任何内容添加到链接中,并在其后面添加//always)。

j5fpnvbx

j5fpnvbx2#

这只是因为您没有提供http://
试试这个

function link_detect($text){

  $ex = "/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[\-;:&=\+\$,\w]+@)?[A-Za-z0-9\.\-]+|(?:www\.|[\-;:&=\+\$,\w]+@)[A-Za-z0-9\.\-]+)((?:\/[\+~%\/\.\w\-_]*)?\??(?:[\-\+=&;%@\.\w_]*)#?(?:[\.\!\/\\\w]*))?)/i";
  return preg_replace($ex,'<a class="click_link" href="http://$1" target="_blank">$1</a>', $text);
}

备选方案:

function text_to_link($str = NULL)
{
    if($str == '' OR !preg_match('/(http|www\.|@)/i', $str))
    {
        return $str;
    }
 
    $lines      = explode("\n", $str); 
    $return     = '';
    while (list($k,$l) = each($lines)) { 
        $l = preg_replace("/([ \t]|^)www\./i", "\\1http://www.", $l);
        $l = preg_replace("/([ \t]|^)ftp\./i", "\\1ftp://ftp.", $l);
        $l = preg_replace("/(http:\/\/[^ )!]+)/i", "<a href=\"\\1\">\\1</a>", $l);
        $l = preg_replace("/(https:\/\/[^ )!]+)/i", "<a href=\"\\1\">\\1</a>", $l);
        $l = preg_replace("/(ftp:\/\/[^ )!]+)/i", "<a href=\"\\1\">\\1</a>", $l);
        $l = preg_replace("/([-a-z0-9_]+(\.[_a-z0-9-]+)*@([a-z0-9-]+(\.[a-z0-9-]+)+))/i", "<a href=\"mailto:\\1\">\\1</a>", $l);
        $return .= $l."\n";
    }
 
    return $return;
}
 
 
/*
*
* ------------------------------------------
* Link
* <a href="http://www.yours.com">http://www.yours.com</a>
* <a href="https://www.yours_with_ssl.com">https://www.yours_with_ssl.com</a>
* ------------------------------------------
*
*/
text_to_link('http://yours.com');
text_to_link('https://yours_with_ssl.com');
 
 
/*
*
* ------------------------------------------
* FTP
* <a href="ftp://username:password@yours.com">ftp://username:password@yours.com</a>
* ------------------------------------------
*
*/
text_to_link('ftp://username:password@yours.com');
 
/*
*
* ------------------------------------------
* Email
* <a href="mailto:w.kristories@gmail.com">mailto:w.kristories@gmail.com</a>
* ------------------------------------------
*
*/
text_to_link('w.kristories@gmail.com');

更新

来自@Mr. coder的评论
但是如果链路已经有http://协议连接到它,那么href将像http://http://www.google.com
是的,更新我的答案为link_detect()

function link_detect($text)
{
  // $ex = "/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[\-;:&=\+\$,\w]+@)?[A-Za-z0-9\.\-]+|(?:www\.|[\-;:&=\+\$,\w]+@)[A-Za-z0-9\.\-]+)((?:\/[\+~%\/\.\w\-_]*)?\??(?:[\-\+=&;%@\.\w_]*)#?(?:[\.\!\/\\\w]*))?)/i";
  // return preg_replace($ex,'<a class="click_link" href="http://$1" 
  $ex = preg_replace("/([ \t]|^)www\./i", "\\1http://www.", $text); // Replace www to http://www
  $ex = preg_replace("/(http:\/\/[^ )!]+)/i", "<a target=\"_blank\" href=\"\\1\">\\1</a>", $ex);
  return $ex;
}

echo link_detect('www.google.com') . "\n";
echo link_detect('http://google.com') . "\n";
echo link_detect('http://www.google.com') . "\n";

相关问题