关于正则表达式:将纯文本URL转换为PHP中的HTML超链接

Convert plain text URLs into HTML hyperlinks in PHP

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

我不希望算法通过任何其他类型的链接(仅http和https)来执行此操作。


这是另一种解决方案,它将捕获所有http / https / www并转换为可单击的链接。

1
2
3
$url = '~(?:(https?)://([^\s<]+)|(www\.[^\s<]+?\.[^\s<]+))(?<![\.,:])~i';
$string = preg_replace($url, '$0', $string);
echo $string;

或者,仅捕获http / https,然后使用下面的代码。

1
2
3
$url = '/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/';  
$string= preg_replace($url, '$0', $string);
echo $string;

编辑:
下面的脚本将捕获所有url类型,并将它们转换为可点击的链接。

1
2
3
$url = '@(http)?(s)?(://)?(([a-zA-Z])([-\w]+\.)+([^\s\.]+[^\s]*)+[^,.\s])@';
$string = preg_replace($url, '$0', $string);
echo $string;

新更新,如果您要去除字符串(s),请使用下面的代码块,感谢@AndrewEllis指出了这一点。

1
2
3
$url = '@(http(s)?)?(://)?(([a-zA-Z])([-\w]+\.)+([^\s\.]+[^\s]*)+[^,.\s])@';
$string = preg_replace($url, '$0', $string);
echo $string;

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

1
2
3
$email = '[email protected]';
$string = $email;
echo $string;

这是一个非常简单的修复程序,但是您必须根据自己的目的对其进行修改。


好吧,Volomike的答案要近得多。为了进一步推动它,这是我所做的,它忽略了超链接末尾的结尾时间。我还考虑了URI片段。

1
2
3
public static function makeClickableLinks($s) {
  return preg_replace('@(https?://([-\w\.]+[-\w])+(:\d+)?(/([\w/_\.#-]*(\?\S+)?[^\.\s])?)?)@', '$1', $s);
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?
function makeClickableLinks($text)
{

        $text = html_entity_decode($text);
        $text ="".$text;
        $text = eregi_replace('(((f|ht){1}tp://)[-a-zA-Z0-9@:%_\+.~#?&//=]+)',
                '\\1', $text);
        $text = eregi_replace('(((f|ht){1}tps://)[-a-zA-Z0-9@:%_\+.~#?&//=]+)',
                '\\1', $text);
        $text = eregi_replace('([[:space:]()[{}])(www.[-a-zA-Z0-9@:%_\+.~#?&//=]+)',
        '\\1\\2', $text);
        $text = eregi_replace('([_\.0-9a-z-]+@([0-9a-z][0-9a-z-]+\.)+[a-z]{2,3})',
        '\\1', $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 [email protected]");
?>


请参阅http://zenverse.net/php-function-to-auto-convert-url-into-hyperlink/。
这就是WordPress的解决方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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] ."$url" . $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] ."$dest" . $ret;
}

function _make_email_clickable_cb($matches) {
    $email = $matches[2] . '@' . $matches[3];
    return $matches[1] ."$email";
}

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("#(]+?>|>))]+?>([^>]+?)#i","$1$3", $ret);
    $ret = trim($ret);
    return $ret;
}

评分最高的答案对我没有帮助,以下链接未正确替换:

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

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

1
2
3
public static function replaceLinks($s) {
    return preg_replace('@(https?://([-\w\.]+)+(:\d+)?(/([\w/_\.%-=#]*(\?\S+)?)?)?)@', '$1', $s);
}

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

因此,请随时发表评论并改进此解决方案。


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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, '$0', $formatText);

    //Catch all links without protocol
    $reg2 = '/(?<=\s|\A)([0-9a-zA-Z\-\.]+\.[a-zA-Z0-9\/]{2,})(?=\s|$|\,|\.)/';
    $formatText = preg_replace($reg2, '$0', $formatText);

    //Catch all emails
    $emailRegex = '/(\S+\@\S+\.\S+)/';
    $formatText = preg_replace($emailRegex, '$1', $formatText);
    $formatText = nl2br($formatText);
    return $formatText;
}

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


来自MkVal的答案有效,但在我们已经有了锚链接的情况下,它将以奇怪的格式呈现文本。

这是在两种情况下都适用的解决方案:

1
2
3
4
5
$s = preg_replace (
   "/(?<!a href=")(?<!src=")((http|ftp)+(s)?:\/\/[^<>\s]+)/i",
   "\\0",
    $s
);


1
2
3
public static function makeClickableLinks($s) {
    return preg_replace('@(https?://([-\w\.]+)+(:\d+)?(/([\w/_\.-]*(\?\S+)?)?)?)@', '$1', $s);
}


我使用的是源自Question2answer的函数,它接受html中的纯文本甚至纯文本链接:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// $html holds the string
$htmlunlinkeds = array_reverse(preg_split('|<[Aa]\s+[^>]+>.*</[Aa]\s*>|', $html, -1, PREG_SPLIT_OFFSET_CAPTURE)); // start from end so we substitute correctly
foreach ($htmlunlinkeds as $htmlunlinked)
{ // and that we don't detect links inside HTML, e.g. <img src="http://...">
    $thishtmluntaggeds = array_reverse(preg_split('/<[^>]*>/', $htmlunlinked[0], -1, PREG_SPLIT_OFFSET_CAPTURE)); // again, start from end
    foreach ($thishtmluntaggeds as $thishtmluntagged)
    {
        $innerhtml = $thishtmluntagged[0];
        if(is_numeric(strpos($innerhtml, '://')))
        { // quick test first
            $newhtml = qa_html_convert_urls($innerhtml, qa_opt('links_in_new_window'));
            $html = substr_replace($html, $newhtml, $htmlunlinked[1]+$thishtmluntagged[1], strlen($innerhtml));
        }
    }
}  
echo $html;

function qa_html_convert_urls($html, $newwindow = false)
/*
    Return $html with any URLs converted into links (with nofollow and in a new window if $newwindow).
    Closing parentheses/brackets are removed from the link if they don't have a matching opening one. This avoids creating
    incorrect URLs from (http://www.question2answer.org) but allow URLs such as http://www.wikipedia.org/Computers_(Software)
*/

{
    $uc = 'a-z\x{00a1}-\x{ffff}';
    $url_regex = '#\b((?:https?|ftp)://(?:[0-9'.$uc.'][0-9'.$uc.'-]*\.)+['.$uc.']{2,}(?::\d{2,5})?(?:/(?:[^\s<>]*[^\s<>\.])?)?)#iu';

    // get matches and their positions
    if (preg_match_all($url_regex, $html, $matches, PREG_OFFSET_CAPTURE)) {
        $brackets = array(
            ')' => '(',
            '}' => '{',
            ']' => '[',
        );

        // loop backwards so we substitute correctly
        for ($i = count($matches[1])-1; $i >= 0; $i--) {
            $match = $matches[1][$i];
            $text_url = $match[0];
            $removed = '';
            $lastch = substr($text_url, -1);

            // exclude bracket from link if no matching bracket
            while (array_key_exists($lastch, $brackets)) {
                $open_char = $brackets[$lastch];
                $num_open = substr_count($text_url, $open_char);
                $num_close = substr_count($text_url, $lastch);

                if ($num_close == $num_open + 1) {
                    $text_url = substr($text_url, 0, -1);
                    $removed = $lastch . $removed;
                    $lastch = substr($text_url, -1);
                }
                else
                    break;
            }

            $target = $newwindow ? ' target="_blank"' : '';
            $replace = '' . $text_url . '' . $removed;
            $html = substr_replace($html, $replace, $match[1], strlen($match[0]));
        }
    }

    return $html;
}

由于接受了包含方括号和其他字符的链接,因此代码有些过多,但可能会有所帮助。


我建议不要像这样在飞行中做很多事情。我更喜欢使用简单的编辑器界面,例如stackoverflow中使用的界面。它称为Markdown。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
$string = 'example.com
www.example.com
http://example.com
https://example.com
http://www.example.com
https://www.example.com'
;

preg_match_all('#(\w*://|www\.)[a-z0-9]+(-+[a-z0-9]+)*(\.[a-z0-9]+(-+[a-z0-9]+)*)+(/([^\s()<>;]+\w)?/?)?#i', $string, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
foreach (array_reverse($matches) as $match) {
  $a = '' . $match[0][0] . '';
  $string = substr_replace($string, $a, $match[0][1], strlen($match[0][0]));
}

echo $string;

结果:

1
2
3
4
5
6
example.com
www.example.com
http://example.com
https://example.com
http://www.example.com
https://www.example.com

我在此解决方案中喜欢的是,它还将www.example.com转换为http://www.example.com,因为不起作用(没有http/https协议,它指向yourdomain.com/www.example.com)。


试试这个:

1
$s = preg_replace('/(?<!href="|">)(?<!src=")((http|ftp)+(s)?:\/\/[^<>\s]+)/is', '\\1', $s);

它跳过现有的链接(如果我们已经有了href,则不会在href内添加href)。否则,它将添加带有空白目标的a href。


如果正确,您要做的是将普通文本转换为http链接。我认为这可以帮助您:

1
2
3
4
5
6
7
8
<?php

   $list = mysqli_query($con,"SELECT * FROM list WHERE name = 'table content'");
   while($row2 = mysqli_fetch_array($list)) {
echo"" . $row2['content']."";

   }  
?>