preg_replace匹配字符串中的所有匹配项,即使在第一次替换之后也是如此


preg_replace to match all match in string even after first replace

此输出:

$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

但是有没有一种更正确、更实用的方法,因为我会把这些模式插入一个很大的数组中。。。

把这些模式放在一个数组中,按长度对该数组进行排序(这样会先检查较长的文本),然后构建正则表达式怎么样?

$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);
}

您要查找的是PCRE中的否定前瞻断言(或查看PCRE备忘单以便于阅读),它告诉引擎查找类似'CALEND'的东西,只要它后面没有直接跟' 2007 RIT'

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

这让你。。。

sometext演示sometext sometext 1234