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

发布于 2024-08-16 05:26:20 字数 152 浏览 3 评论 0 原文

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

我不希望算法对任何其他类型的链接执行此操作,仅使用 http 和 https。

I have a simple commenting system where people can submit hyperlinks inside the plain text field. When I display these records back from the database and into the web page, what RegExp in PHP can I use to convert these links into HTML-type anchor links?

I don't want the algorithm to do this with any other kind of link, just http and https.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(15

|煩躁 2024-08-23 05:26:20

这是另一个解决方案,这将捕获所有 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;

或者,如果只是捕获 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;

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

$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;

新的更新,如果您让字符串去掉 (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;

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

$email = '<a href="mailto:[email protected]">[email protected]</a>';
$string = $email;
echo $string;

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

我提供了多个答案,因为某些服务器的设置不同,因此一个答案可能适用于某些服务器,但不适用于其他服务器,但我希望答案对您有用,如果没有,请告诉我,希望我可以想出另一个解决方案。

有多个脚本,因为有些 PHP 文件需要不同的脚本,有些服务器的设置也不同,而且每个脚本都有不同的要求,有些只需要 HTTP/S,有些需要 WWW,有些需要 FTP/S,每个脚本的工作方式取决于设置了用户自己的脚本,我为每个脚本提供了一些文本以及他们所做的事情。

Here is another solution, This will catch all http/https/www and convert to clickable links.

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

Alternatively for just catching http/https then use the code below.

$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;

EDIT:
The script below will catch all URL types and convert them to clickable links.

$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;

The new update, If you're having the string strip the (s) then use the below code block, Thanks to @AndrewEllis for pointing this out.

$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;

Here's a very simple solution for the URL not displaying correctly.

$email = '<a href="mailto:[email protected]">[email protected]</a>';
$string = $email;
echo $string;

It is a very simple fix but you will have to modify it for your own purpose.

I've provided multiple answers as some servers are set up differently, so one answer may work for some but not for others, but I hope the answer(s) work for you and if not then let me know, and hopefully, I can come up with another solution.

There are multiple scripts as some PHP files require different scripts also some servers are set up differently, Plus each has different requirements, Some want just HTTP/S, some want WWW and some want FTP/S, Each one will work depending on how the users own scripts are set up, I provided some text with each one with what they do.

轮廓§ 2024-08-23 05:26:20

好吧,沃洛米克的答案更接近。为了更进一步,我做了以下操作,忽略了超链接末尾的尾随句点。我还考虑了 URI 片段。

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

Well, Volomike's answer is much closer. And to push it a bit further, here's what I did for it to disregard the trailing period at the end of the hyperlinks. I also considered URI fragments.

public static function makeClickableLinks($s) {
  return preg_replace('@(https?://([-\w\.]+[-\w])+(:\d+)?(/([\w/_\.#-]*(\?\S+)?[^\.\s])?)?)@', '<a href="$1" target="_blank">$1</a>', $s);
}
茶底世界 2024-08-23 05:26:20

请参阅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;
}

Refer http://zenverse.net/php-function-to-auto-convert-url-into-hyperlink/.
This is how wordpress solve it

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;
}
知你几分 2024-08-23 05:26:20
<?
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 [email protected]");
?>
<?
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 [email protected]");
?>
灼痛 2024-08-23 05:26:20

评分最高的答案没有为我完成这项工作,以下链接未正确替换:

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);
}

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

所以请随意发表评论并改进这个解决方案。

The most rated answer didn't do the job for me, following link was not replaced correctly:

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

After some google searches and some tests, this is what I came up with:

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

I'm not an expert in regex, actually it quite confuses me :)

So feel free to comment and improve this solution.

扛起拖把扫天下 2024-08-23 05:26:20

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

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;
}

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

Here is my code to format all the links inside text, including emails, urls with and without protocol.

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;
}

Please comment the url that doesn't work. I'll try to update the regex.

夜声 2024-08-23 05:26:20

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

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

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

The answer from MkVal works but in the case we already have the anchor link, it will render the text in weird format.

Here is the solution which works for me in both cases:

$s = preg_replace ( 
    "/(?<!a href=\")(?<!src=\")((http|ftp)+(s)?:\/\/[^<>\s]+)/i",
    "<a href=\"\\0\" target=\"blank\">\\0</a>",
    $s
);
︶葆Ⅱㄣ 2024-08-23 05:26:20

试试这个:

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

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

Try this one:

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

It skips the existing links (if we already have a href, it won't add a href inside of a href). Otherwise it will add the a href with blank target.

ぃ弥猫深巷。 2024-08-23 05:26:20
public static function makeClickableLinks($s) {
    return preg_replace('@(https?://([-\w\.]+)+(:\d+)?(/([\w/_\.-]*(\?\S+)?)?)?)@', '<a href="$1">$1</a>', $s);
}
public static function makeClickableLinks($s) {
    return preg_replace('@(https?://([-\w\.]+)+(:\d+)?(/([\w/_\.-]*(\?\S+)?)?)?)@', '<a href="$1">$1</a>', $s);
}
把回忆走一遍 2024-08-23 05:26:20
<?php
/**
 * Turn all URLs in clickable links.
 * 
 * @param string $value
 * @param array  $protocols  http/https, ftp, mail, twitter
 * @param array  $attributes
 * @return string
 */
public function linkify($value, $protocols = array('http', 'mail'), array $attributes = array())
{
    // Link attributes
    $attr = '';
    foreach ($attributes as $key => $val) {
        $attr .= ' ' . $key . '="' . htmlentities($val) . '"';
    }
    
    $links = array();
    
    // Extract existing links and tags
    $value = preg_replace_callback('~(<a .*?>.*?</a>|<.*?>)~i', function ($match) use (&$links) { return '<' . array_push($links, $match[1]) . '>'; }, $value);
    
    // Extract text links for each protocol
    foreach ((array)$protocols as $protocol) {
        switch ($protocol) {
            case 'http':
            case 'https':   $value = preg_replace_callback('~(?:(https?)://([^\s<]+)|(www\.[^\s<]+?\.[^\s<]+))(?<![\.,:])~i', function ($match) use ($protocol, &$links, $attr) { if ($match[1]) $protocol = $match[1]; $link = $match[2] ?: $match[3]; return '<' . array_push($links, "<a $attr href=\"$protocol://$link\">$link</a>") . '>'; }, $value); break;
            case 'mail':    $value = preg_replace_callback('~([^\s<]+?@[^\s<]+?\.[^\s<]+)(?<![\.,:])~', function ($match) use (&$links, $attr) { return '<' . array_push($links, "<a $attr href=\"mailto:{$match[1]}\">{$match[1]}</a>") . '>'; }, $value); break;
            case 'twitter': $value = preg_replace_callback('~(?<!\w)[@#](\w++)~', function ($match) use (&$links, $attr) { return '<' . array_push($links, "<a $attr href=\"https://twitter.com/" . ($match[0][0] == '@' ? '' : 'search/%23') . $match[1]  . "\">{$match[0]}</a>") . '>'; }, $value); break;
            default:        $value = preg_replace_callback('~' . preg_quote($protocol, '~') . '://([^\s<]+?)(?<![\.,:])~i', function ($match) use ($protocol, &$links, $attr) { return '<' . array_push($links, "<a $attr href=\"$protocol://{$match[1]}\">{$match[1]}</a>") . '>'; }, $value); break;
        }
    }
    
    // Insert all link
    return preg_replace_callback('/<(\d+)>/', function ($match) use (&$links) { return $links[$match[1] - 1]; }, $value);
}

不是我的代码,我从这里得到它 https://gist.github.com/jasny/2000705

<?php
/**
 * Turn all URLs in clickable links.
 * 
 * @param string $value
 * @param array  $protocols  http/https, ftp, mail, twitter
 * @param array  $attributes
 * @return string
 */
public function linkify($value, $protocols = array('http', 'mail'), array $attributes = array())
{
    // Link attributes
    $attr = '';
    foreach ($attributes as $key => $val) {
        $attr .= ' ' . $key . '="' . htmlentities($val) . '"';
    }
    
    $links = array();
    
    // Extract existing links and tags
    $value = preg_replace_callback('~(<a .*?>.*?</a>|<.*?>)~i', function ($match) use (&$links) { return '<' . array_push($links, $match[1]) . '>'; }, $value);
    
    // Extract text links for each protocol
    foreach ((array)$protocols as $protocol) {
        switch ($protocol) {
            case 'http':
            case 'https':   $value = preg_replace_callback('~(?:(https?)://([^\s<]+)|(www\.[^\s<]+?\.[^\s<]+))(?<![\.,:])~i', function ($match) use ($protocol, &$links, $attr) { if ($match[1]) $protocol = $match[1]; $link = $match[2] ?: $match[3]; return '<' . array_push($links, "<a $attr href=\"$protocol://$link\">$link</a>") . '>'; }, $value); break;
            case 'mail':    $value = preg_replace_callback('~([^\s<]+?@[^\s<]+?\.[^\s<]+)(?<![\.,:])~', function ($match) use (&$links, $attr) { return '<' . array_push($links, "<a $attr href=\"mailto:{$match[1]}\">{$match[1]}</a>") . '>'; }, $value); break;
            case 'twitter': $value = preg_replace_callback('~(?<!\w)[@#](\w++)~', function ($match) use (&$links, $attr) { return '<' . array_push($links, "<a $attr href=\"https://twitter.com/" . ($match[0][0] == '@' ? '' : 'search/%23') . $match[1]  . "\">{$match[0]}</a>") . '>'; }, $value); break;
            default:        $value = preg_replace_callback('~' . preg_quote($protocol, '~') . '://([^\s<]+?)(?<![\.,:])~i', function ($match) use ($protocol, &$links, $attr) { return '<' . array_push($links, "<a $attr href=\"$protocol://{$match[1]}\">{$match[1]}</a>") . '>'; }, $value); break;
        }
    }
    
    // Insert all link
    return preg_replace_callback('/<(\d+)>/', function ($match) use (&$links) { return $links[$match[1] - 1]; }, $value);
}

Not my code, I got it from here https://gist.github.com/jasny/2000705

來不及說愛妳 2024-08-23 05:26:20

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

I recommend not to do many things on fly like this. I prefer to use simple editor interface like the one used in stackoverflow. It is called Markdown.

云雾 2024-08-23 05:26:20

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

// $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 = '<a href="' . $text_url . '" rel="nofollow"' . $target . '>' . $text_url . '</a>' . $removed;
            $html = substr_replace($html, $replace, $match[1], strlen($match[0]));
        }
    }

    return $html;
}

由于接受包含括号和其他字符的链接,代码有点多,但可能有帮助。

I am using a function that originated from question2answer, it accepts plain text and even plain text links in html:

// $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 = '<a href="' . $text_url . '" rel="nofollow"' . $target . '>' . $text_url . '</a>' . $removed;
            $html = substr_replace($html, $replace, $match[1], strlen($match[0]));
        }
    }

    return $html;
}

A bit much code due to accepting links that hold brackets and other characters, but probably it helps.

缘字诀 2024-08-23 05:26:20

在 HTML 中查找纯文本链接

我真的很喜欢 这个答案 - 但我需要一个解决方案来处理非常内部可能的纯文本链接简单的 HTML 文本:

<p>I found a really cool site you might like:</p>
<p>www.stackoverflow.com</p>

这意味着我需要正则表达式模式来忽略 html 字符 <>

正则表达式调整

所以我更改了部分模式为 [^\s\>\<] 而不是 \S

  • \S - 不是空格;匹配任何非空白字符(制表符、空格、换行符)
  • [^] - 否定集;匹配不在集合中的任何字符

我的答案中的函数版本

我需要除 HTML 之外的另一种格式,因此我将正则表达式与其替换项分开以适应这一点。

我还添加了一种仅返回在数组中找到的链接/电子邮件的方法,这样我就可以将它们作为关系保存在我的帖子中(非常适合稍后为它们制作元卡......以及分析!) )。

更新:连续的句点匹配

我得到了类似 there...it 的文本匹配 - 所以我想确保我没有得到任何包含连续点的匹配。

注意:为了解决这个问题,我添加了一个额外的格式字符串来撤消匹配它们,以避免必须重做这些可靠的 url 正则表达式。

/***
 * based on this answer: https://stackoverflow.com/a/49689245/2100636
 *
 * @var $text String
 * @var $format String - html (<a href=""...), short ([link:https://somewhere]), other (https://somewhere)
 */
public function formatLinksInString(
    $string,
    $format = 'html', 
    $returnMatches = false
) {
    $formatProtocol = $format == 'html'
        ? '<a href="$0" target="_blank" title="$0">$0</a>'
        : ($format == 'short' || $returnMatches ? '[link:$0]' : '$0');

    $formatSansProtocol = $format == 'html'
        ? '<a href="//$0" target="_blank" title="$0">$0</a>'
        : ($format == 'short' || $returnMatches ? '[link://$0]' : '$0');

    $formatMailto = $format == 'html'
        ? '<a href="mailto:$1" target="_blank" title="$1">$1</a>'
        : ($format == 'short' || $returnMatches ? '[mailto:$1]' : '$1');

    $regProtocol = '/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,}(\/[^\<\>\s]*)?/';
    $regSansProtocol = '/(?<=\s|\A|\>)([0-9a-zA-Z\-\.]+\.[a-zA-Z0-9\/]{2,})(?=\s|$|\,|\<)/';
    $regEmail = '/([^\s\>\<]+\@[^\s\>\<]+\.[^\s\>\<]+)\b/';
    $consecutiveDotsRegex = $format == 'html'
        ? '/<a[^\>]+[\.]{2,}[^\>]*?>([^\<]*?)<\/a>/'
        : '/\[link:.*?\/\/([^\]]+[\.]{2,}[^\]]*?)\]/';

    // Protocol links
    $formatString = preg_replace($regProtocol, $formatProtocol, $string);
    // Sans Protocol Links
    $formatString = preg_replace($regSansProtocol, $formatSansProtocol, $formatString); // use formatString from above
    // Email - Mailto - Links
    $formatString = preg_replace($regEmail, $formatMailto, $formatString); // use formatString from above
    // Prevent consecutive periods from getting captured
    $formatString = preg_replace($consecutiveDotsRegex, '$1', $formatString);

    if ($returnMatches) {
        // Find all [x:link] patterns
        preg_match_all('/\[.*?:(.*?)\]/', $formatString, $matches);

        current($matches); // to move pointer onto groups
        return next($matches); // return the groups
    }

    return $formatString;
}

Finding Plain Text Links inside HTML

I really liked this answer - yet I needed a solution for possible plain text links that are inside very simple HTML text:

<p>I found a really cool site you might like:</p>
<p>www.stackoverflow.com</p>

This meant I needed the regex patterns to ignore the html chars < and >

Regex Adjustment

So I changed parts of the patterns to [^\s\>\<] instead of \S

  • \S - not white-space; matches any char that is not white-space (tab, space, newline)
  • [^] - a negated set; matches any char not in the set

My version of the function from this answer

I needed another format in addition to HTML so I separated out the regexes from their replacements to accommodate this.

I also added a way to return just the links/emails found into an array so I can save them as a relationship on my posts (great for making meta cards for them later ...and for analytics!).

UPDATE: Consecutive periods were matching

I was getting matches for text like there...it - So I wanted to ensure I didn't get any matches that included consecutive dots.

Note: To accomplish fixing this, I added an additional format string to undo matching them to avoid having to redo these otherwise reliable url regexes.

/***
 * based on this answer: https://stackoverflow.com/a/49689245/2100636
 *
 * @var $text String
 * @var $format String - html (<a href=""...), short ([link:https://somewhere]), other (https://somewhere)
 */
public function formatLinksInString(
    $string,
    $format = 'html', 
    $returnMatches = false
) {
    $formatProtocol = $format == 'html'
        ? '<a href="$0" target="_blank" title="$0">$0</a>'
        : ($format == 'short' || $returnMatches ? '[link:$0]' : '$0');

    $formatSansProtocol = $format == 'html'
        ? '<a href="//$0" target="_blank" title="$0">$0</a>'
        : ($format == 'short' || $returnMatches ? '[link://$0]' : '$0');

    $formatMailto = $format == 'html'
        ? '<a href="mailto:$1" target="_blank" title="$1">$1</a>'
        : ($format == 'short' || $returnMatches ? '[mailto:$1]' : '$1');

    $regProtocol = '/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,}(\/[^\<\>\s]*)?/';
    $regSansProtocol = '/(?<=\s|\A|\>)([0-9a-zA-Z\-\.]+\.[a-zA-Z0-9\/]{2,})(?=\s|$|\,|\<)/';
    $regEmail = '/([^\s\>\<]+\@[^\s\>\<]+\.[^\s\>\<]+)\b/';
    $consecutiveDotsRegex = $format == 'html'
        ? '/<a[^\>]+[\.]{2,}[^\>]*?>([^\<]*?)<\/a>/'
        : '/\[link:.*?\/\/([^\]]+[\.]{2,}[^\]]*?)\]/';

    // Protocol links
    $formatString = preg_replace($regProtocol, $formatProtocol, $string);
    // Sans Protocol Links
    $formatString = preg_replace($regSansProtocol, $formatSansProtocol, $formatString); // use formatString from above
    // Email - Mailto - Links
    $formatString = preg_replace($regEmail, $formatMailto, $formatString); // use formatString from above
    // Prevent consecutive periods from getting captured
    $formatString = preg_replace($consecutiveDotsRegex, '$1', $formatString);

    if ($returnMatches) {
        // Find all [x:link] patterns
        preg_match_all('/\[.*?:(.*?)\]/', $formatString, $matches);

        current($matches); // to move pointer onto groups
        return next($matches); // return the groups
    }

    return $formatString;
}
浮世清欢 2024-08-23 05:26:20
$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 = '<a href="'.(strpos($match[1][0], '/') ? '' : 'http://') . $match[0][0].'">' . $match[0][0] . '</a>';
  $string = substr_replace($string, $a, $match[0][1], strlen($match[0][0]));
}

echo $string;

结果:

example.com
<a href="http://www.example.com">www.example.com</a>
<a href="http://example.com">http://example.com</a>
<a href="https://example.com">https://example.com</a>
<a href="http://www.example.com">http://www.example.com</a>
<a href="https://www.example.com">https://www.example.com</a>

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

$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 = '<a href="'.(strpos($match[1][0], '/') ? '' : 'http://') . $match[0][0].'">' . $match[0][0] . '</a>';
  $string = substr_replace($string, $a, $match[0][1], strlen($match[0][0]));
}

echo $string;

Result:

example.com
<a href="http://www.example.com">www.example.com</a>
<a href="http://example.com">http://example.com</a>
<a href="https://example.com">https://example.com</a>
<a href="http://www.example.com">http://www.example.com</a>
<a href="https://www.example.com">https://www.example.com</a>

What I like in this solution is that it also converts www.example.com to http://www.example.com because <a href="www.example.com"></a> doesn't work (without http/https protocol it points to yourdomain.com/www.example.com).

清晨说晚安 2024-08-23 05:26:20

如果我是对的,你要做的就是将普通文本转换为http链接。我认为以下内容可以提供帮助:

<?php

   $list = mysqli_query($con,"SELECT * FROM list WHERE name = 'table content'"); 
   while($row2 = mysqli_fetch_array($list)) {
echo "<a target='_blank' href='http://www." . $row2['content']. "'>" . $row2['content']. "</a>";

   }  
?>

If am right, what you want to do is turn ordinary text into http links. Here's what I think can help:

<?php

   $list = mysqli_query($con,"SELECT * FROM list WHERE name = 'table content'"); 
   while($row2 = mysqli_fetch_array($list)) {
echo "<a target='_blank' href='http://www." . $row2['content']. "'>" . $row2['content']. "</a>";

   }  
?>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文