PHPでの正規表現によるコールバックを利用した置換
次の文字列があるとします:
<?php
$str = '2+3= 3+5= 7+8=';
?>
数値+数値= という形式のすべての構造を見つけ、等号の後に加算結果が表示されるようにする必要があるとします。
このようなタスクを解決するには、関数 preg_replace_callback を利用すると便利です。
この関数は、関数 preg_replace と同様に動作します(正規表現に基づいて検索と置換を行います)が、見つかった部分に対して追加の操作を実行することができます。
最初のパラメータとして関数は正規表現を受け取り、2番目は置換する文字列(またはコールバック)、3番目は置換が行われる文字列を受け取ります。
このとき、2番目のパラメータには、見つかった各一致に対して呼び出されるコールバック関数を渡す必要があります。
コールバックの最初のパラメータには、見つかった内容が格納される変数を指定する必要があります。 この変数は、見つかった一致のキャプチャグループ(括弧でキャプチャされた部分)の配列となります。
実際に試してみましょう。最初の数値を最初のキャプチャグループに、2番目の数値を2番目のキャプチャグループに格納しながら、部分文字列を取得するコードを書いてみます:
<?php
$str = '2+3= 3+5= 7+8=';
preg_replace_callback('#(\d+)\+(\d+)=#', function($match) {
var_dump($match);
}, $str);
?>
その結果、var_dump が3回実行され、順番に以下が出力されます:
['2+3=', '2', '3']
['3+5=', '3', '5']
['7+8=', '7', '7']
次に進みます。各一致は、コールバックが return を通じて返す内容に置き換えられます。
例として、検索対象の各部分文字列を記号 '!' に置き換えてみましょう:
<?php
$str = '2+3= 3+5= 7+8=';
$res = preg_replace_callback('#(\d+)\+(\d+)=#', function($match) {
return '!';
}, $str);
echo $res; // '! ! !' を出力します
?>
次に、各部分文字列をその中の数値の合計に置き換えてみましょう:
<?php
$str = '2+3= 3+5= 7+8=';
$res = preg_replace_callback('#(\d+)\+(\d+)=#', function($match) {
return $match[1] + $match[2];
}, $str);
echo $res; // '5 8 13' を出力します
?>
つまり、私たちのタスクはほぼ解決しました。 あとは、合計値の前に元の部分文字列が残るようにすれば完了です。そのためには、合計の前にゼロ番目のキャプチャグループの内容を挿入します:
<?php
$str = '2+3= 3+5= 7+8=';
$res = preg_replace_callback('#(\d+)\+(\d+)=#', function($match) {
return $match[0] . ($match[1] + $match[2]);
}, $str);
echo $res; // '2+3=5 3+5=8 7+8=13' を出力します
?>
以下の文字列が与えられます:
<?php
$str = 'The numbers are 3, 7 and 12';
?>
文字列内のすべての数値をその2乗に置き換えてください。
期待される結果:
'The numbers are 9, 49 and 144'
以下の文字列が与えられます:
<?php
$str = '2023-01-15 2022-12-31 2024-05-20';
?>
すべての日付を 日.月.年 形式に変換してください。
以下の文字列が与えられます:
<?php
$str = 'Costs: $15, $20, $100';
?>
すべての価格を 10% 増やしてください。