web-dev-qa-db-fra.com

PHP preg_replace: correspondance insensible à la casse avec remplacement sensible à la casse

J'utilise preg_replace dans PHP pour rechercher et remplacer des mots spécifiques dans une chaîne, comme ceci:

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

Ce qui donne le résultat 'poire poire'.

Ce que j'aimerais être en mesure de faire correspondre un mot d'une manière insensible à la casse, mais respectez sa casse quand il est remplacé - donnant le résultat "Poire poire".

L'œuvre suivante, mais me semble un peu longue:

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

Y a-t-il une meilleure manière de faire cela?

Mise à jour: Suite à une excellente requête soulevée ci-dessous, aux fins de cette tâche, je veux seulement respecter la "casse du titre" - donc si la première lettre d'un mot est une majuscule.

23
colin

Je pense à cette implémentation pour les cas courants:

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

-il est plus compliqué, bien sûr, mais correspond à la demande d'origine pour n'importe quel poste. Si vous ne recherchez que la première lettre, cela pourrait être une exagération (voir la réponse de @ Jon alors)

11
Alma Do

Vous pouvez le faire avec preg_replace_callback, mais c'est encore plus long:

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

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

Ce code examine simplement la mise en majuscule du premier caractère de la correspondance pour déterminer avec quoi remplacer; vous pouvez adapter le code pour faire quelque chose de plus complexe à la place.

10
Jon

Voici la solution que j'ai utilisée:

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

Dans les meilleurs mots que je peux, je vais essayer d'expliquer pourquoi cela fonctionne: Envelopper votre terme de recherche avec () signifie que je souhaite accéder à cette valeur ultérieurement. Comme il s'agit du premier élément des pars du RegEx, il est accessible avec $1, comme vous pouvez le voir dans le paramètre de substitution

4
Luke Madhanga