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

3
这将输出:
$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替换第一个在$san_field中找到的匹配项CALEND。 我知道可以这样做:
$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个回答

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

这就是我在问题中所写的。但是,如果CALEND出现在数组中CALEND 2007 RIT之前,那么我期望的结果将无法实现。感谢preg_quote,我会使用它。 - Perocat
1
按长度对数组进行排序怎么样? - Martin.
不错的想法,我只是在思考这个是否“真正有效”,或者是否存在一些情况无法运作。 - Perocat
我想不出任何情况下这不起作用的例子。 - Martin.
请注意,您的自定义usort函数无法处理多字节字符串,并且是不必要的,因为您可以使用rsort($replace, SORT_STRING | SORT_FLAG_CASE); - Casimir et Hippolyte

2
你所寻找的是 PCRE 中称为“负向先行断言”的功能(或者可以查看PCRE cheat sheet以便更容易阅读),它告诉引擎在查找类似于'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)

这句话的意思是:“这给了你...”,接下来的引用块中有一些文本,其中包括“PROS”、“sometext”和“sometext1234”。

这将匹配并替换“2007”。 - Martin.
是的,它会。那是他们最初的正则表达式。并没有作为问题的一部分提到,所以我认为他们可能需要那个。 - Sherif
1
我不认为这是过度的。但我们必须记住那句经典的话:“我有一个问题,所以我用了正则表达式……现在我有两个问题”。 - Sherif
谢谢您的评论。我有一个数组,其中包含 strings = array('stuff1', 'stuff2', 'stuff3', 'stuff1 stuff2', 'stuff2 stuff3'); 所有这些值都可以以 ' '|- |-- 开头并以 --| -|' ' 结尾,所以问题是我不能使用 str_replace。除此之外,str_replace 从第一个数组成员开始到最后一个成员。因此,如果 stuff2 stuff3stuff2 之后出现,则会替换 stuff2 而不是 stuff2 stuff3 - Perocat
1
是的,我明白了。你的例子很糟糕,不能描绘出你真正的问题,但再次提醒你XY 问题 XY 问题 XY 问题 XY 问题 XY 问题 - Sherif
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接