preg_replace()删除重复的字符并用相应的字符替换它们?

时间:2014-07-16 18:32:23

标签: php preg-replace repeat

$s='123///456***789';

现在我尝试替换重复的///***

$s=preg_replace('!\/+!',"/",$s);
$s=preg_replace('!\*+!',"*",$s);

结果是123/456*789确定

我正在尝试删除一个模式的重复但我无法知道如何为每个重复字符设置相应的字符

$s=preg_replace('![\/\*]+!',"/",$s);

结果为123/456/789,但我需要它与上述结果一样 - 123/456*789

2 个答案:

答案 0 :(得分:2)

使用反向引用(http://de2.php.net/manual/en/regexp.reference.back-references.php):

$s='123///456***789';
$s = preg_replace ('~([\/\*])\1+~', '\1', $s);
printf ("%s\n", $s);

答案 1 :(得分:1)

您可以使用preg_replace_callback来实现:

$s=preg_replace_callback('!(\*+|\/+)!' ,
  function($match){
    //whatever we match MULTIPLE times - replace it with one time "that".
    return substr($match[1],0,1); //first matchgroup
  }
,$s);

旁注:模式![\/\*]+!也将匹配/*/*/* - 这不是您(可能)想要实现的。您应该使用(\*+|\/+)代替。

附注2 :在MatchGroups内部,您无需转义。 [/*]+等于你提供的正则表达式。


如果您将模式设计得更加棘手,您可以省略回调,并使用反向引用:

$s=preg_replace('!(?:(\*)\*+|(\/)\/+)!' , "$1$2", $s);

说明:

匹配一个时间*/,然后是其中的一个或多个。您的第一个匹配组(分别为第二个)现在只包含一个有问题的符号。因此,***的整个匹配将替换为您的第一个(第二个)匹配组 - 现在是一个*(分别为/)。

使用$1$2替换是安全的,因为由于OR(|)其中一个匹配组始终为空。

但我更喜欢解决方案,因为它更清晰。