在PHP中将纯文本URL转换为HTML超链接

Vol*_*ike 57 php regex hyperlink preg-replace

我有一个简单的评论系统,人们可以在纯文本字段中提交超链接.当我将这些记录从数据库显示回网页时,我可以使用PHP中的RegExp将这些链接转换为HTML类型的锚链接吗?

我不希望算法使用任何其他类型的链接,只需http和https.

Rud*_*gns 60

这是另一个解决方案,这将捕获所有http/https/www并转换为可点击的链接.

$url = '~(?:(https?)://([^\s<]+)|(www\.[^\s<]+?\.[^\s<]+))(?<![\.,:])~i'; 
$string = preg_replace($url, '<a href="$0" target="_blank" title="$0">$0</a>', $string);
echo $string;
Run Code Online (Sandbox Code Playgroud)

或者只是为了捕获http/https,然后使用下面的代码.

$url = '/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/';   
$string= preg_replace($url, '<a href="$0" target="_blank" title="$0">$0</a>', $string);
echo $string;
Run Code Online (Sandbox Code Playgroud)

编辑:下面的脚本将捕获所有网址类型并将其转换为可点击的链接.

$url = '@(http)?(s)?(://)?(([a-zA-Z])([-\w]+\.)+([^\s\.]+[^\s]*)+[^,.\s])@';
$string = preg_replace($url, '<a href="http$2://$4" target="_blank" title="$0">$0</a>', $string);
echo $string;
Run Code Online (Sandbox Code Playgroud)

新的更新,如果你有字符串条带(s)然后使用下面的代码块,感谢@AndrewEllis指出这一点.

$url = '@(http(s)?)?(://)?(([a-zA-Z])([-\w]+\.)+([^\s\.]+[^\s]*)+[^,.\s])@';
$string = preg_replace($url, '<a href="http$2://$4" target="_blank" title="$0">$0</a>', $string);
echo $string;
Run Code Online (Sandbox Code Playgroud)

这是一个非常简单的URL无法正确显示的解决方案.

$email = '<a href="mailto:email@email.com">email@email.com</a>';
$string = $email;
echo $string;
Run Code Online (Sandbox Code Playgroud)

这是一个非常简单的修复,但您必须根据自己的目的修改它.

  • 正确的正则表达式应该是`$ url ='@(http(s)?)?(://)?(([a-zA-Z])([ - \w] + \.)+([^小号\] + [^\S]*)+ [^ ,.\S])@';`.注意第一个`(s)的放置?`.你最初如何通过将其转换为"uperaswesome.com"来打破像"superawesome.com"这样的域名. (3认同)
  • 您的函数存在 XSS 漏洞,例如:`http://google.com/"onclick="alert(0)`,结果:`&lt;a href="http://google.com/"onclick="alert (0)" target="_blank" title="http://google.com/"onclick="alert(0)"&gt;http://google.com/"onclick="alert(0)&lt;/a&gt; `,但您可以在 `$string` 之前使用 `htmlspecialchars` 来修复它。 (3认同)

MkV*_*Val 39

好吧,Volomike的答案更接近.而且为了进一步推动它,这就是我为它做的事情,忽略了超链接末尾的尾随时期.我也考虑过URI片段.

public static function makeClickableLinks($s) {
  return preg_replace('@(https?://([-\w\.]+[-\w])+(:\d+)?(/([\w/_\.#-]*(\?\S+)?[^\.\s])?)?)@', '<a href="$1" target="_blank">$1</a>', $s);
}
Run Code Online (Sandbox Code Playgroud)

  • 此代码不执行URL的HTML转义.最重要的是,包含&符号的URL将产生无效的HTML. (7认同)

Luc*_*eis 8

<?
function makeClickableLinks($text)
{

        $text = html_entity_decode($text);
        $text = " ".$text;
        $text = eregi_replace('(((f|ht){1}tp://)[-a-zA-Z0-9@:%_\+.~#?&//=]+)',
                '<a href="\\1" target=_blank>\\1</a>', $text);
        $text = eregi_replace('(((f|ht){1}tps://)[-a-zA-Z0-9@:%_\+.~#?&//=]+)',
                '<a href="\\1" target=_blank>\\1</a>', $text);
        $text = eregi_replace('([[:space:]()[{}])(www.[-a-zA-Z0-9@:%_\+.~#?&//=]+)',
        '\\1<a href="http://\\2" target=_blank>\\2</a>', $text);
        $text = eregi_replace('([_\.0-9a-z-]+@([0-9a-z][0-9a-z-]+\.)+[a-z]{2,3})',
        '<a href="mailto:\\1" target=_blank>\\1</a>', $text);
        return $text;
}

// Example Usage
echo makeClickableLinks("This is a test clickable link: http://www.websewak.com  You can also try using an email address like test@websewak.com");
?>
Run Code Online (Sandbox Code Playgroud)

  • @Luca,您是否知道"eregi_replace"和其他POSIX正则表达式函数已被弃用? (7认同)

小智 7

请参阅http://zenverse.net/php-function-to-auto-convert-url-into-hyperlink/.这就是wordpress如何解决它

function _make_url_clickable_cb($matches) {
    $ret = '';
    $url = $matches[2];

    if ( empty($url) )
        return $matches[0];
    // removed trailing [.,;:] from URL
    if ( in_array(substr($url, -1), array('.', ',', ';', ':')) === true ) {
        $ret = substr($url, -1);
        $url = substr($url, 0, strlen($url)-1);
    }
    return $matches[1] . "<a href=\"$url\" rel=\"nofollow\">$url</a>" . $ret;
}

function _make_web_ftp_clickable_cb($matches) {
    $ret = '';
    $dest = $matches[2];
    $dest = 'http://' . $dest;

    if ( empty($dest) )
        return $matches[0];
    // removed trailing [,;:] from URL
    if ( in_array(substr($dest, -1), array('.', ',', ';', ':')) === true ) {
        $ret = substr($dest, -1);
        $dest = substr($dest, 0, strlen($dest)-1);
    }
    return $matches[1] . "<a href=\"$dest\" rel=\"nofollow\">$dest</a>" . $ret;
}

function _make_email_clickable_cb($matches) {
    $email = $matches[2] . '@' . $matches[3];
    return $matches[1] . "<a href=\"mailto:$email\">$email</a>";
}

function make_clickable($ret) {
    $ret = ' ' . $ret;
    // in testing, using arrays here was found to be faster
    $ret = preg_replace_callback('#([\s>])([\w]+?://[\w\\x80-\\xff\#$%&~/.\-;:=,?@\[\]+]*)#is', '_make_url_clickable_cb', $ret);
    $ret = preg_replace_callback('#([\s>])((www|ftp)\.[\w\\x80-\\xff\#$%&~/.\-;:=,?@\[\]+]*)#is', '_make_web_ftp_clickable_cb', $ret);
    $ret = preg_replace_callback('#([\s>])([.0-9a-z_+-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})#i', '_make_email_clickable_cb', $ret);

    // this one is not in an array because we need it to run last, for cleanup of accidental links within links
    $ret = preg_replace("#(<a( [^>]+?>|>))<a [^>]+?>([^>]+?)</a></a>#i", "$1$3</a>", $ret);
    $ret = trim($ret);
    return $ret;
}
Run Code Online (Sandbox Code Playgroud)


Ste*_*ner 6

对于我来说,评分最高的答案并没有完成这项工作,因为链接未被正确替换:

http://www.fifa.com/worldcup/matches/round255951/match=300186487/index.html#nosticky

经过一些谷歌搜索和一些测试,这就是我提出的:

public static function replaceLinks($s) {
    return preg_replace('@(https?://([-\w\.]+)+(:\d+)?(/([\w/_\.%-=#]*(\?\S+)?)?)?)@', '<a href="$1">$1</a>', $s);
}
Run Code Online (Sandbox Code Playgroud)

我不是正则表达式的专家,实际上它让我很困惑:)

因此,请随意评论并改进此解决方案.


Hoa*_*ung 5

这是我的代码,用于格式化文本内的所有链接,包括电子邮件、带协议和不带协议的网址。

public function formatLinksInText($text)
{
    //Catch all links with protocol      
    $reg = '/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,}(\/\S*)?/'; 
    $formatText = preg_replace($reg, '<a href="$0" style="font-weight: normal;" target="_blank" title="$0">$0</a>', $text);

    //Catch all links without protocol
    $reg2 = '/(?<=\s|\A)([0-9a-zA-Z\-\.]+\.[a-zA-Z0-9\/]{2,})(?=\s|$|\,|\.)/';
    $formatText = preg_replace($reg2, '<a href="//$0" style="font-weight: normal;" target="_blank" title="$0">$0</a>', $formatText);

    //Catch all emails
    $emailRegex = '/(\S+\@\S+\.\S+)\b/';
    $formatText = preg_replace($emailRegex, '<a href="mailto:$1" style="font-weight: normal;" target="_blank" title="$1">$1</a>', $formatText);
    $formatText = nl2br($formatText);
    return $formatText;
}
Run Code Online (Sandbox Code Playgroud)

请评论无效的网址。我会尝试更新正则表达式。