字符串替换在一个字符串中具有完全(部分)匹配的两个匹配项

时间:2019-02-27 10:47:25

标签: php

我有一个变量$text,它是纯文本,可以在一行文本中包含一个或多个电子邮件地址。我使用正则表达式查找这些电子邮件地址,然后将其转换为可点击的<a href="mailto:....etc地址。这是我的代码,并带有可以正常工作的示例:

$text = "this is the text that has a email@email.com in it and also test@email.com.";

if(preg_match_all('/[\p{L}0-9_.-]+@[0-9\p{L}.-]+\.[a-z.]{2,6}\b/u',$text,$mails)){

foreach($mails[0] as $mail ){
    $text = str_replace($mail,'<a href="mailto:'.$mail.'">'.$mail.'</a>',$text);
    }
}

或查看此live demo。当我的变量$text中有两个电子邮件地址完全匹配(部分匹配)时,就会出现问题。例如sometest@email.comtest@email.com。这是另一个live demo。问题在于字符串替换也在部分匹配中发生(因为它也是完全匹配)。如何绕开这个问题?

3 个答案:

答案 0 :(得分:2)

为什么不使用preg_replace
str_replace可以覆盖以前的比赛。

这应该对您有好处:

echo preg_replace(
    '/([\p{L}0-9_.-]+@[0-9\p{L}.-]+\.[a-z.]{2,6}\b)/u',
    '<a href="mailto:$1">$1</a>',
    $text
);

请注意,我必须稍微修改正则表达式并将其包装在括号中。
这样便可以在替换中引用它。

Live demo

答案 1 :(得分:1)

比赛之前,您必须赶上角色,以确保比赛完全成功:

if(preg_match_all('/(.)([\p{L}0-9_.-]+@[0-9\p{L}.-]+\.[a-z.]{2,6}\b)/u',$text,$mails))

----------------------------------- ^

然后,您只需要修改一下str_replace参数
               var_dump($ mails);

$id = 0;
foreach($mails[2] as $mail ){
   $text = str_replace($mails[1][$id].$mail,'$mails[1][$id].<a href="mailto:'.$mail.'">'.$mail.'</a>',$text);
   $id ++;
}

例如:https://3v4l.org/qYpHo

答案 2 :(得分:1)

喜欢...

<?php

$string = "this is the text that has a email@email.com in it and also test@email.com.";

$search = array ( "!(\s)([_\.0-9a-z-]+@([0-9a-z][0-9a-z-]+\.)+[a-z]{2,3})!i",  
"!^([_\.0-9a-z-]+@([0-9a-z][0-9a-z-]+\.)+[a-z]{2,3})!i" );

$replace = array ( "\\1<a href=\"mailto:\\2\">\\2</a>", 
"<a href=\"mailto:\\1\">\\1</a>" );

echo preg_replace ( $search, $replace, $string );

?>

结果...

this is the text that has a <a href="mailto:email@email.com">email@email.com</a> in it and also <a href="mailto:test@email.com">test@email.com</a>.