【问题标题】:preg_replace() Remove repeating characters and replace them with the corresponding characters?preg_replace() 去掉重复的字符,换成对应的字符?
【发布时间】:2014-07-16 18:32:22
【问题描述】:
$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

【问题讨论】:

  • 所以你想在 1 个语句中做到这一点?
  • @EL 请再次检查我的答案。它现在应该可以工作了。
  • @EL 总是有 3 个/或者可以有 2 个或 4 个吗?
  • @tastro 是的。我很好奇是否有可能在一个声明中
  • @tastro 我可以超过 3 岁,可以是任何字符

标签: php preg-replace repeat


【解决方案1】:

使用反向引用 (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 的意思
  • @EL: \1 是对第一个子模式的“结果”的引用。
  • 这种情况下不需要转义/*
  • 这是我在更新之前提供的相同答案...我的被否决...他被选为答案...o_O
  • @tastro:诀窍是 double 反向引用,一个在正则表达式中,另一个在替换中。
【解决方案2】:

您可以使用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 个或多个。您的第一个匹配组(分别为第二个)现在将仅包含一个相关标志。因此,*** 的整个匹配将替换为您的第一个(分别为第二个)匹配组 - 现在是单个 *(分别为 /)。

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

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

【讨论】:

  • 第一个没试过。但是第二个对我不起作用。 ://
  • @tastro:您阅读了评论以从模式中删除空白?
  • 对不起,我的错。它正在工作。但不适用于这样的事情:123///*/456***789反正...不知道这是否可能。
  • @tastro:例如,两者都返回123/*/456*789 - 如果我得到正确的操作,这是预期的。
  • 我得到:$s=preg_replace("@([\/\*])[\/\*]+@i", '$1' ,$s); // input: 123/*/456*789 output: 123/456*789 我的例子。但无论如何也没关系。已经有太多聊天cmets了。 ;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-11
  • 2012-04-16
  • 2012-11-29
  • 2021-02-01
  • 1970-01-01
  • 2022-11-15
  • 2012-12-25
相关资源
最近更新 更多