用HTML链接替换文本中的URL

58

这里有一个设计思路:例如,当我在文本区域中放置链接:

http://example.com

如何让PHP检测到它是一个http://链接并将其打印为

print "<a href='http://www.example.com'>http://www.example.com</a>";

我记得以前做过类似的事情,但不是万无一失的,对于复杂的链接经常会出问题。

另一个好主意是,如果你有这样的链接

http://example.com/test.php?val1=bla&val2blablabla%20bla%20bla.bl

修复它使其正常运作。

print "<a href='http://example.com/test.php?val1=bla&val2=bla%20bla%20bla.bla'>";
print "http://example.com/test.php";
print "</a>";

这只是一个想法... stackoverflow 也可能会用得上它 :D

有什么想法吗?


哦,我看到 Stack Overflow 已经做了第一部分了... 发布代码吧,你知道你想这么做的 :D - Angel.King.47
17个回答

0

如果你想信任IANA,你可以在那里获取当前官方支持的顶级域名列表,例如:

  $validTLDs = 
explode("\n", file_get_contents('http://data.iana.org/TLD/tlds-alpha-by-domain.txt')); //get the official list of valid tlds
  array_shift($validTLDs); //throw away first line containing meta data
  array_pop($validTLDs); //throw away last element which is empty

使Søren Løvborg的第二个解决方案更简洁,并避免了更新列表的麻烦,现在新的顶级域名被如此轻率地抛弃;)


0

这个将URL转换为文本,同时保留主页URL不变。希望这能帮助你节省时间。享受吧。

class RegClass 
{ 

     function preg_callback_url($matches) 
     { 
        //var_dump($matches); 
        //Get the matched URL  text <a>text</a>
        $text = $matches[2];
        //Get the matched URL link <a href ="http://www.test.com">text</a>
        $url = $matches[1];

        if($url=='href ="http://www.test.com"'){
         //replace all a tag as it is
         return '<a href='.$url.' rel="nofollow"> '.$text.' </a>'; 

         }else{
         //replace all a tag to text
         return " $text " ;
         }
} 
function ParseText($text){ 

    $text = preg_replace( "/www\./", "http://www.", $text );
        $regex ="/http:\/\/http:\/\/www\./"
    $text = preg_replace( $regex, "http://www.", $text );
        $regex2 = "/https:\/\/http:\/\/www\./";
    $text = preg_replace( $regex2, "https://www.", $text );

        return preg_replace_callback('/<a\s(.+?)>(.+?)<\/a>/is',
                array( &$this,        'preg_callback_url'), $text); 
      } 

} 
$regexp = new RegClass();
echo $regexp->ParseText($text);

这个类使用了 preg_replace_callback 函数来搜索和替换 URL 为文本。如果在 ParseText 函数中出现任何错误,只需用实际的模式替换 $regex 和 regex2 即可。 - amarjit singh

0

这对我有用(将其中一个答案转换为 PHP 函数)

function make_urls_from_text ($text){
   return preg_replace('/(http[s]{0,1}\:\/\/\S{4,})\s{0,}/ims', '<a href="$1" target="_blank">$1 </a>', $text);
}

0

我创建的这个类对我的需求来说是有效的,不过需要一些改进;

class addLink
{
    public function link($string)
    {
        $expression = "/(?i)\b((?:https?:\/\/|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,63}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'\".,<>?«»“”‘’]))/";
        if(preg_match_all($expression, $string, $matches) == 1)// If the pattern is found then
        {
            $string = preg_replace($expression, '<a href="'.$matches[0][0].'" target="_blank">$1</a>', $string);
        }

        return $string;       
    }
}

使用此代码的示例:

include 'PHP/addLink.php';

if(class_exists('addLink')) 
{                  
    $al = new addLink();                  
}
else{
    echo 'Class not found...';
} 

$paragraph = $al->link($paragraph);

[a-z]{2,4} 实际上是顶级域名的缩写,可以查看:TLD列表 - Toto
此外,你的正则表达式匹配http://qdj$$$-=, demo,不确定它是一个有效的URL ;) - Toto
我根据RFC 1034将TLD长度更改为63,并进行了上述更新... - user13611442
我目前正在阅读RFC 1035来修复我的正则表达式模式匹配问题... - user13611442

0

这只是Dharmendra Jadon发布的解决方案的变体,如果您喜欢它,请投票支持他的解决方案!

我只是添加了一个参数,使在新窗口中打开链接(target="_blank")成为可选项,因为我在其他一些解决方案中看到了这一点,并且喜欢这种灵活性:

function MakeUrls($str, $popup = FALSE)
{
    $find=array('`((?:https?|ftp)://\S+[[:alnum:]]/?)`si','`((?<!//)(www\.\S+[[:alnum:]]/?))`si');

    $replace=array('<a href="$1"' . ($popup ? ' target="_blank"' : '') . '>$1</a>', '<a href="http://$1"' . ($popup ? ' target="_blank"' : '') . '>$1</a>');

    return preg_replace($find,$replace,$str);
}

如果模式中没有“任意字符”点,则s模式修饰符是无用的。 - mickmackusa
如果您的链接在引号内(例如xxxxxxxx "http://www.bbc.com/list"<br>Received yyyyy),则此操作将失败。请参见https://regex101.com/r/puRu94/1 - user1432181

-1

这应该可以获取您的 Twitter 用户名,而不触及您的电子邮件 /(?<=^|(?<=[^a-zA-Z0-9-.]))@([A-Za-z]+[A-Za-z0-9]+)/i


1
你是不是从 https://dev59.com/oHE95IYBdhLWcg3wdtmj#6351873 复制了我的答案,然后粘贴到了我的问题上,但这与我的问题无关。稍微给点信用至少可以避免被踩哦! - Angel.King.47

-2

虽然匹配完整的URL规范很困难,但这是一个通常能够很好地完成工作的正则表达式:

([\w-]+(\.[\w-]+)*@([a-z0-9-]+(\.[a-z0-9-]+)*?\.[a-z]{2,6}|(\d{1,3}\.){3}\d{1,3})(:\d{4})?)

然而,在 preg_replace 中使用它,您需要对其进行转义。如下:

$pattern = "/([\\w-]+(\\.[\\w-]+)*@([a-z0-9-]+(\\.[a-z0-9-]+)*?\\.[a-z]{2,6}|(\\d{1,3}\\.){3}\\d{1,3})(:\\d{4})?)/";
$replaced_texttext = preg_replace($pattern, '<a href="$0" title="$0">$0</a>', $text);

这就是为什么我讨厌 preg_replace... 我会测试一下并告诉你 :D - Angel.King.47
这个链接是否对您有用?抱歉,您需要点击链接以获取完整信息。Stackoverflow将其截断了。 - Angel.King.47
有趣的是,它适用于电子邮件而不适用于URL...哈哈,但对于像mail@stack.co.uk这样的电子邮件失败了。 - Angel.King.47
正则表达式缺少一些反斜杠,这就是为什么它不能正确匹配那些URL的原因。现在应该已经修复了。 - André Eriksson
很抱歉要说这个..但不行..它只能针对电子邮件,而对于像.co.uk这样的域名仍然存在相同的问题,.uk部分会被省略。而且它根本不能用于URL。 - Angel.King.47

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接