PHP preg_replace:大小写不敏感匹配,但保留原有的大小写替换。

30

我正在使用PHP中的preg_replace函数来查找和替换字符串中的特定单词,例如:

$subject = "Apple apple";
print preg_replace('/\bapple\b/i', 'pear', $subject);

这将会得到结果为“pear pear”。

我希望能够以不区分大小写的方式匹配一个单词,但在替换时保留它的大小写 - 得到结果为“Pear pear”。

以下方法可行,但对我来说有点冗长:

$pattern = array('/Apple\b/', '/apple\b/');
$replacement = array('Pear', 'pear');
$subject = "Apple apple";
print preg_replace($pattern, $replacement, $subject);

有没有更好的方法来做这件事?

更新:根据下面提出的优秀问题,为了完成此任务,我只想尊重“标题大小写”-无论单词的第一个字母是否大写。


唯一仍不清楚的是:如果您要替换的单词和原始单词长度不同,并且原始单词在更高的位置有大写字母,那该怎么办?例如 'applE''pear',那么呢? - Alma Do
1
非常好的观点。对于这个特定的任务,我只想尊重“标题大小写”(因此第一个字母是否大写)。非常感谢您进一步澄清。 - colin
4个回答

17

我有一个普遍情况下的实现想法:

$data    = 'this is appLe and ApPle';
$search  = 'apple';
$replace = 'pear';

$data = preg_replace_callback('/\b'.$search.'\b/i', function($matches) use ($replace)
{
   $i=0;
   return join('', array_map(function($char) use ($matches, &$i)
   {
      return ctype_lower($matches[0][$i++])?strtolower($char):strtoupper($char);
   }, str_split($replace)));
}, $data);

//var_dump($data); //"this is peaR and PeAr"

当然,实际情况比这更加复杂,但是原始需求适用于任何位置。如果你只需要第一个字母,那么这可能会过度(请参见@Jon的答案)。


12

您可以使用preg_replace_callback来完成这个任务,但这会更加冗长:

$replacer = function($matches) {
    return ctype_lower($matches[0][0]) ? 'pear' : 'Pear';
};

print preg_replace_callback('/\bapple\b/i', $replacer, $subject);

这段代码只是查看匹配的第一个字符的大小写来确定要替换的内容;您可以将代码改编为执行更复杂的操作。


我尝试了你的代码,但是出现了可捕获的致命错误:无法将闭包类对象转换为字符串... - c3cris
@c3cris,我在上面的代码片段中错误地写成了preg_replace而不是preg_replace_callback,尽管第一行中的提到是正确的。已修复。 - Jon
这是一个更加优雅的解决方案。一眼就能看懂,而且更加简短。+1 - JustCarty

7
这是我使用的解决方案:
$result = preg_replace("/\b(foo)\b/i", "<strong>$1</strong>", $original);

在我最好的措辞下,我将尝试解释为什么这样做有效:用()包装您的搜索术语意味着我稍后想要访问此值。由于它是正则表达式中pars的第一项,因此可以使用$1访问它,正如您在替换参数中所看到的那样。

看看这个和预期答案之间的差异。这是对所有工程师“保持简单”的重要提醒。 - user5132647
4
这个答案没有提供期望的结果/功能。 - mickmackusa
太简单了!我怎么会忘记反向引用呢?谢谢你! - sdlins
2
这是 $1 还是 $0? - Federico González Brizzio

1
$text = 'Grey, grey and grey';
$text = Find_and_replace_in_lowercase_and_uppercase('grey', 'gray', $text);
echo $text; //Returns 'Gray, gray and gray'

function Find_and_replace_in_lowercase_and_uppercase($find_term, $replace_term, $text)
{
        $text = Find_and_replace_in_lowercase($find_term, $replace_term, $text);
        $text = Find_and_replace_in_uppercase($find_term, $replace_term, $text);
        return $text;

}
function Find_and_replace_in_lowercase($find_term, $replace_term, $text)
{
        $find_term = lcfirst($find_term);
        $replace_term = lcfirst($replace_term);
        $text = preg_replace("/$find_term/",$replace_term,$text);
        return $text;
}
function Find_and_replace_in_uppercase($find_term, $replace_term, $text)
{
        $find_term = ucfirst($find_term);
        $replace_term = ucfirst($replace_term);
        $text = preg_replace("/$find_term/",$replace_term,$text);
        return $text;
}

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