PHP preg_replace: Case insensitive match with case

2019-01-22 13:15发布

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

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

3条回答
Juvenile、少年°
2楼-- · 2019-01-22 13:37

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

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

查看更多
Rolldiameter
3楼-- · 2019-01-22 13:47

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)

查看更多
何必那么认真
4楼-- · 2019-01-22 13:55

This is the solution that I used:

$result = preg_replace("/\b(foo)\b/i", "<strong>$1</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

查看更多
登录 后发表回答