使用preg_replace避免重复替换

时间:2017-05-06 17:35:26

标签: php regex

这是我的php功能。 它取代了已被替换的东西,从而弄乱了HTML。 如何防止第一次更换同一文本的第二次更换?

function text2link($str){
$str="\r\n$str\r\n";
$pattern= array(  
'/(http:\/\/)(.*?)(\n|\<|"|\s)/is', 
'/(https:\/\/)(.*?)(\n|\<|"|\s)/is', 
'/\[url\=(.*?)\](.*?)\[\/url\]/is' 
//'/[^\"|\>](http:\/\/)([a-zA-Z0-9\?\&\%\.\;\:\/\=\+\_\-]*)[^\"|\<]/is', 
//'/[^\"|\>](https:\/\/)([a-zA-Z0-9\?\&\%\.\;\:\/\=\+\_\-]*)[^\"|\<]/is', 
//'/[^\"|\>](ftp:\/\/)([a-zA-Z0-9\?\&\%\.\;\:\/\=\+\_\-]*)[^\"|\<]/is' 
 );
$replace=array(  ' <a target="_blank" href="http://$2">$2</a> $3', ' <a target="_blank" href="https://$2">$2</a> $3', '<a target="_blank" href="$1">$2</a>', 
//' <a target="_blank" href="http://$2">$2</a> ', ' <a target="_blank" href="https://$2">$2</a> ', ' <a target="_blank" href="ftp://$2">ftp: $2</a> '
);
$str = preg_replace( $pattern, $replace, $str);
return $str;
}


echo text2link(' A link to [url=https://www.google.com] secure google [/url] and www.google.com this is http://www.google.com and another [url=http://www.google.com] google [/url]  '); exit;

如果您运行上述代码,则会将第一个链接视为:

<a target="_blank" href=" <a target="_blank" href="https://www.google.com">">www.google.com]</a>  secure google </a>  

应该是:

<a target="_blank" href="https://www.google.com"> secure google </a>

出于某种原因,http部分将再次被替换。

已经被[url]模式取代的那些已经使用先前的模式再次被替换。 评论模式是我试图检测报价或更大/更少的符号并避免替换的地方。没有工作......

3 个答案:

答案 0 :(得分:1)

我希望这就是你要找的东西。在这里,我们使用preg_match_all收集我们要替换的所有匹配项,然后逐个替换。

正则表达式: \[([a-z]+)\=((?:https?:\/\/)?(?:www\.)?[^\]]+)\](.*?)\[\/\\1\]

  

1。 [([a-z]+)\=这将匹配[,然后匹配一些字符a-z,然后=

     

2. ((?:https?:\/\/)?(?:www\.)?[^\]]+)\]这将捕获完整链接,然后]

     

3。 (.*?)\[这将匹配所有[

     

4。 \/\\1\]这将匹配\,然后首先捕获的群组就像这里首先捕获的群组url然后]一样端。

Try this code snippet here

function text2link($str)
{
    preg_match_all("/\[([a-z]+)\=((?:https?:\/\/)?(?:www\.)?[^\]]+)\](.*?)\[\/\\1\]/", $str,$matches);
    foreach($matches[0] as $key => $toReplace)
    {
        $str=str_replace($toReplace, '<a target="_blank" href="'.$matches[2][$key].'">'.$matches[3][$key]."</a>", $str);
    }
    return $str;
}

echo text2link(' A link to [url=https://www.google.com] secure google [/url] and www.google.com this is http://www.google.com and another [url=http://www.google.com] google [/url]  ');

<强>输出:

A link to <a target="_blank" href="https://www.google.com"> secure google </a> and www.google.com this is http://www.google.com and another <a target="_blank" href="http://www.google.com"> google </a>

答案 1 :(得分:1)

如果我理解正确,您只希望用html <a>链接替换方括号内的链接。

这将执行:

$str=' A link to [url=https://www.google.com] secure google [/url] and www.google.com this is http://www.google.com and another [url=http://www.google.com] google [/url]  ';
$pattern="/(\[url=(https?[^]]+)\] ?(.*?) ?\[\/url\])/i";
$replace="<a target=\"_blank\" href=\"$2\">$3</a>";
echo preg_replace($pattern,$replace,$str);  // I recommend trim() around preg_replace() here

这是正则表达式模式的Regex Pattern Demo,因此您可以看到它是如何工作的。

输出:

 A link to <a target="_blank" href="https://www.google.com">secure google</a> and www.google.com this is http://www.google.com and another <a target="_blank" href="http://www.google.com">google</a>

如果您想要包含没有使用协议的方括号网址:

(\[url=((?:https?:\/\/)?[^]]+)\] ?(.*?) ?\[\/url\])

Regex Pattern Demo

如果您想在缺少时添加www.

Regex Pattern Demo

代码:

$str='An https://www link to [url=https://www.google.com] secure google [/url] and www.google.com this is http://www.google.com and another [url=http://www.google.com] google [/url] and this is just www. [url=www.google.com] google [/url] and this url has no www. [url=google.com] google [/url]';
$pattern="/(\[url=(https?:\/\/)?(www.)?([^]]+)\] ?(.*?) ?\[\/url\])/i";
$replace='<a target=\"_blank\" href=\"$2www.$4\">$5</a>';
echo preg_replace($pattern,$replace,$str);

输出:

An https://www link to <a target=\"_blank\" href=\"https://www.google.com\">secure google</a> and www.google.com this is http://www.google.com and another <a target=\"_blank\" href=\"http://www.google.com\">google</a> and this is just www. <a target=\"_blank\" href=\"www.google.com\">google</a> and this url has no www. <a target=\"_blank\" href=\"www.google.com\">google</a>

答案 2 :(得分:0)

@mickmackusa感谢您的代码!对它进行了一些扩展,下面的这个工作用于字符串中的各种类型的URL等。谢谢 :) 在此发布,以便其他人也可以使用它。

$str=' A link to [url=https://www.google.com] secure google [/url] and www.google.com this is http://www.google.com and another [url=http://www.google.com] google [/url]  ';

$pattern=array(
'/(\[url=(https?[^]]+)\] ?(.*?) ?\[\/url\])/is',
 '/([\\s|\\n])(http:\/\/)(.*?)([\\n|\<|\"|\\s])/is',
 '/([\\s|\\n])(https:\/\/)(.*?)([\\n|\<|\"|\\s])/is',
'/([\\s|\\n])(www\.)(.*?)([\\n|\<|\"|\\s])/is'
);
$replace=array(
' <a target="_blank" href="$2">$3</a> ',
' <a target="_blank" href="http://$3">$3</a> ',
' <a target="_blank" href="https://$3">$3</a> ',
' <a target="_blank" href="http://www.$3">$3</a> '
);
echo preg_replace($pattern,$replace,$str);