preg_replace即使在第一次替换后也匹配字符串中的所有匹配

时间:2015-11-09 00:29:22

标签: php regex preg-replace preg-match preg-match-all

输出:

$san_field = 'sometext PROS sometext sometext1234 CALEND 2007 RIT';
$pattern = '/(\s|^|- |--)(?:CALEND|2007|CALEND 2007 RIT)(--| -|\s|$)/i';
echo preg_replace($pattern, ' ', $san_field)

>> sometext PROS sometext sometext1234 2007 RIT

我想替换CALEND 2007 RIT而不是CALEND,这是$san_field上找到的第一个匹配项。 我知道我可以这样做:

$san_field = 'sometext PROS sometext sometext1234 CALEND 2007 RIT';
$pattern = '/(\s|^|- |--)(?:CALEND 2007 RIT|CALEND|2007)(--| -|\s|$)/i';
echo preg_replace($pattern, ' ', $san_field)

>> sometext PROS sometext sometext1234

但是有更正确和实用的方法,因为我会将这些模式插入到一个非常大的数组中......

2 个答案:

答案 0 :(得分:2)

如何将这些模式放到数组中,按长度排序该数组(首先检查更长的文本)并在之后构建正则表达式?

$replace = ["2007", "CALEND", "CALEND 2007 RIT"];
usort($replace, function($a, $b){
    return strlen($b) - strlen($a);
});
$san_field = 'sometext PROS sometext sometext1234 CALEND 2007 RIT';
$pattern = '/(\s|^|- |--)(?:'.(implode('|', $replace)).')(--| -|\s|$)/i';
echo preg_replace($pattern, ' ', $san_field)

此外,preg_quote这些值是个好主意,以防您在其中放入一些特殊字符。

foreach($replace as &$item) {
    $item = preg_quote($item);
}

答案 1 :(得分:2)

您正在寻找的内容在PCRE中被称为负面预测断言(或查看PCRE cheat sheet以便于阅读),这会让发动机看起来像对于类似,col1,col2 1,1,0 2,0,1 3,1,1 的内容,只要在您的情况下不直接跟'CALEND'

' 2007 RIT'

哪个给你......

  

sometext PROS sometext sometext1234