👻

複数の文字の置換

2023/05/17に公開

PHPで複数の文字列を一度に置換したい場合に利用するstr_replace()strtr()ですが、挙動が少し違うようです。

要件

「東京都新宿区新宿3丁目」という文字列があって、

  • 新宿区は<span>新宿区</span>に、
  • 新宿は<b>新宿</b>に、

それぞれ置換したいとします。

置換前: 「東京都新宿区新宿3丁目」
完成形: 「東京都<span>新宿区</span><b>新宿</b>3丁目」

1. str_replace()

最初に思いついた方法が以下になります。

str_replace
$str = '東京都新宿区新宿3丁目';
$array = [
    '新宿区' => '<span>新宿区</span>',
    '新宿' => '<b>新宿</b>',
];

echo str_replace(array_keys($array), array_values($array), $str);
// '東京都<span><b>新宿</b>区</span><b>新宿</b>3丁目'

str_replace()では、配列の先頭から順番に文字列を置換します。

まず「東京都新宿区新宿3丁目」の新宿区という文字列を置換して
「東京都<span>新宿区</span>新宿3丁目」になります。

次に「東京都<span>新宿区</span>新宿3丁目」から新宿を探してもう一度置換を行うので
「東京都<span><b>新宿</b>区</span><b>新宿</b>3丁目」となります。

2. str_replace()

配列の順番を変えてみます。

str_replace
$str = '東京都新宿区新宿3丁目';
$array = [
    '新宿' => '<b>新宿</b>',
    '新宿区' => '<span>新宿区</span>',
];

echo str_replace(array_keys($array), array_values($array), $str);
// '東京都<b>新宿</b>区<b>新宿</b>3丁目'

念のためもう一度。str_replace()では、配列の先頭から順番に文字列を置換します。

この場合、「東京都新宿新宿3丁目」の新宿という文字列を置換して
「東京都<b>新宿</b>区<b>新宿</b>3丁目」になります。

置換後の文字列には新宿区という文字列は無いので、そのまま出力されます。

3. strtr()

strtr
$str = '東京都新宿区新宿3丁目';
$array = [
    '新宿' => '<b>新宿</b>',
    '新宿区' => '<span>新宿区</span>',
];

echo strtr($str, $array);
// '東京都<span>新宿区</span><b>新宿</b>3丁目'

これで欲しい結果が取得できました。

strtr()の場合、配列の順番は関係がなく、キーの文字列の長いものから順に調べて置換をし、一度置換された部分の文字列は置換対象から外れるようです。

新宿と新宿区では、もちろん「新宿区」の方が文字列としては長いので、先に「新宿区」が「<span>新宿区</span>」に置換されます。

その後、置換された新宿区は対象外になるので、「東京都 <span>新宿区</span> 新宿3丁目」が置換されて
東京都<span>新宿区</span><b>新宿</b>3丁目となります。

参考

https://qiita.com/ryoo_ss/items/8ca05de64d7c583df0dc

https://norm-nois.com/blog/archives/4088

Discussion