web-dev-qa-db-ja.com

PHP preg_replace:大文字と小文字を区別しない置換と大文字と小文字を区別しない一致

PHPでpreg_replaceを使用して、次のように文字列内の特定の単語を検索および置換しています。

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

結果は「梨梨」になります。

私ができるようにしたいのは、大文字と小文字を区別しない方法でWordを照合することですが、置き換えられた場合は大文字と小文字を区別します-結果は「Pear pear」になります。

次のように機能しますが、少し長い感じがします。

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

これを行うより良い方法はありますか?

更新:以下の優れたクエリに加えて、このタスクの目的では「タイトルの大文字小文字」のみを尊重したいので、単語の最初の文字が大文字であるかどうかを確認します。

23
colin

私は一般的なケースのこの実装を念頭に置いています:

$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の回答を参照してください)。

11
Alma Do

preg_replace_callbackでこれを行うことができますが、それはさらに時間がかかります:

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

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

このコードは、一致する最初の文字の大文字を調べて、何に置き換えるかを決定します。代わりに、コードを変更して、より複雑なことを行うことができます。

10
Jon

これは私が使用したソリューションです:

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

これが機能する理由を説明します。検索用語を()でラップすると、後でこの値にアクセスすることになります。これはRegExのparsの最初の項目であるため、置換パラメーターで確認できるように、$1を使用してアクセスできます。

4
Luke Madhanga