Php 如何编写一个函数,将纯文本转换为包含5种URL类型的可单击链接

Php 如何编写一个函数,将纯文本转换为包含5种URL类型的可单击链接,php,regex,Php,Regex,以下是文本内部的链接类型。链接可以以空格开头,也可以是较长字符串的一部分,例如:sometexthttp://www.domain.extension?parameters 1. http://domain.extension?parameter 2. http://subdomain.domain.extension?parameters 3. https://domain.extension?parameter 4. https://subdomain.domain.extension?

以下是文本内部的链接类型。链接可以以空格开头,也可以是较长字符串的一部分,例如:sometexthttp://www.domain.extension?parameters

1. http://domain.extension?parameter  
2. http://subdomain.domain.extension?parameters
3. https://domain.extension?parameter
4. https://subdomain.domain.extension?parameters
5. www.domain.extension?parameter  
我编写了以下函数,该函数部分工作。第一个正则表达式查找包含“www.”的所有字符串,并向其添加前缀“http://”。第二个正则表达式将它们包装成“a”标记


从www、http://或https://开始,直到第一个空格,这一切如何? 正则表达式搜索

(?<link>(www\.|https?://)[^\s]+)
(?(www\.| https?:/)[^\s]+)
正则表达式替换

<a href='${link}'>${link}</a>

这并不完美,但可能会有所帮助。此外,我不能100%确定以上正则表达式语法在您的情况下是否正确

编辑:无法使用www.phpliveregex.com使其与命名组一起工作。这里有一个没有它们的解决方案:

preg_replace("/((www\.|https?:\/\/)[^\s]+)/", "<a href='$1'>$1</a>", $input_lines);
preg\u replace(“/((www\.\https?:\/\/)[^\s]+)/”,“,$input\u行);
使用“负向后看”限定符确保“www”前面没有正斜杠“/”通过排除所有http://和https://的不希望的插入来解决问题:)

这是从原始问题修改的第一个正则表达式

((?<![/])((www).([-\w\.]+)+(:\d+)?(/([\w/_\.%-=#]*(\?\S+)?)?)?))
(?

下面是一个完整的工作函数,它使用了第一个带有负向后看的正则表达式以及Simo建议的第二个正则表达式

function MakeClickableLinks($text) {       
$text = preg_replace('@((?<![/])((www\.).([-\w\.]+)+(:\d+)?(/([\w/_\.%-=#]*(\?\S+)?)?)?))@',  ' http://$1',  $text);              
$text = preg_replace("/((https?:\/\/)[^\s]+)/",   '<a href="$1" rel="nofollow" target="_blank" >$1</a>',  $text);         
return $text;               
}
函数MakeClickableLinks($text){

$text=preg_replace('@)(?我认为原因是您首先替换所有www.xy.tld链接,然后替换所有http)://www.xy.tld links。您是否尝试关闭那些preg_replace调用?如果您这样做,您自然必须将第一个调用的替换值更改为
。案例1。反转正则表达式不起作用,因为第二个函数仍将尝试在已以http:.Case 2开头的每个字符串中添加http://内容如果rexex被反转并且替换值被切换,那么它也不起作用,因为第一个正则表达式将额外的http://添加到http(s)//和第二个正则表达式包装,第二个正则表达式封装第一个正则表达式的缺陷输出。WhatAh,右。然后您可以考虑查看同一个问题。危险危险。如果<代码> COSDSDFSDFS/代码>实际上是一个有效的TLD?如果<代码> SoTeXWWWW>代码>实际上是<代码> SSSSSS .com中的一个有效的主机名。/代码>域?如果你可以依赖有限的域集,这将是有帮助的。但更重要的是,我建议你尝试清理源数据,以便使处理更可靠。目前,你的正则表达式替换需要做出一些大的假设。嗨,Simo。be上的问号的目的是什么在整理正则表达式时,它只会抛出一个错误,即编译失败,因为没有可重复的内容。(?xxxyyyzzz)是一个命名组。您可以在正则表达式替换中使用${some_name}引用该名称。我不确定preg_replace的语法是否正确。快速谷歌搜索显示旧的php版本可能接受(?pxxyyyzzz)已编辑的答案不使用命名组。您的正则表达式可以工作,但不会在只有“www”的链接前面添加http://没有http://前缀的链接将导致一些php应用程序尝试查找具有此标题的内部页面,并抛出一个错误,因为找不到这些页面。这就是为什么我的第一个正则表达式会添加缺少的http://前缀,而第二个正则表达式会将链接包装在标记中。但是,你的正则表达式将更干净、更简单地替代我的第二个正则表达式。在第二个正则表达式中,w为什么
https?:\/\/
在括号中?
((?<![/])((www).([-\w\.]+)+(:\d+)?(/([\w/_\.%-=#]*(\?\S+)?)?)?))
function MakeClickableLinks($text) {       
$text = preg_replace('@((?<![/])((www\.).([-\w\.]+)+(:\d+)?(/([\w/_\.%-=#]*(\?\S+)?)?)?))@',  ' http://$1',  $text);              
$text = preg_replace("/((https?:\/\/)[^\s]+)/",   '<a href="$1" rel="nofollow" target="_blank" >$1</a>',  $text);         
return $text;               
}