PHP preg_replace:区分大小写的匹配与区分大小写的替换

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19317493/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 19:15:45  来源:igfitidea点击:

PHP preg_replace: Case insensitive match with case sensitive replacement

phpregexpreg-replace

提问by colin

I'm using preg_replace in PHP to find and replace specific words in a string, like this:

我在 PHP 中使用 preg_replace 来查找和替换字符串中的特定单词,如下所示:

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

Which gives the result 'pear pear'.

这给出了结果“梨梨”。

What I'd like to be able to do is to match a word in a case insensitive way, but respect it's case when it is replaced - giving the result 'Pear pear'.

我希望能够做的是以不区分大小写的方式匹配一个单词,但在替换它时要尊重它的大小写 - 给出结果“梨梨”。

The following works, but seems a little long winded to me:

以下工作,但对我来说似乎有点冗长:

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

Is there a better way to do this?

有一个更好的方法吗?

Update: Further to an excellent query raised below, for the purposes of this task I only want to respect 'title case' - so whether or not the first letter of a word is a capital.

更新:除了下面提出的一个很好的查询之外,为了这个任务的目的,我只想尊重“标题案例”——所以一个词的第一个字母是否是大写的。

采纳答案by Alma Do

I have in mind this implementation for common case:

我想到了这种常见情况的实现:

$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"

-it's more complicated, of course, but fit original request for any position. If you're looking for only first letter, this could be an overkill (see @Jon's answer then)

- 当然,它更复杂,但适合任何职位的原始要求。如果您只寻找第一个字母,这可能有点矫枉过正(然后请参阅@Jon 的回答)

回答by Jon

You could do this with preg_replace_callback, but that's even more long winded:

你可以用 来做到这一点preg_replace_callback,但这更啰嗦:

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

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

This code just looks at the capitalization of the first character of the match to determine what to replace with; you could adapt the code to do something more involved instead.

此代码仅查看匹配项的第一个字符的大小写,以确定要替换的内容;你可以修改代码来做一些更复杂的事情。

回答by Luke Madhanga

This is the solution that I used:

这是我使用的解决方案:

$result = preg_replace("/\b(foo)\b/i", "<strong></strong>", $original);

In the best words that I can I'll try explain why this works: Wrapping your search term with ()means I want to access this value later. As it is the first item in pars in the RegEx, it is accessible with $1, as you can see in the substitution parameter

用我能说的最好的话,我会尝试解释为什么会这样:将您的搜索词包装起来()意味着我想稍后访问这个值。由于它是 RegEx 中 pars 中的第一项,因此可以使用 访问$1,正如您在替换参数中看到的