結論
配列を渡す機能は代替できないが、参照は(もっと柔軟な形で)代替できる。そう、 mb_ereg_replace_callback()
を使えばね。
環境
PHP5.4.1以降、mbstringが有効になっている必要があります。
前提
PHPのマルチバイト文字対応は、UTF-8が前提になっているものがあります。 preg_replace()
関数もその一つです。この関数はマルチバイト文字に対応していますが、UTF-8以外の文字コードには対応していません。
しかし例えばEUC-JPなど、どうしても古い文字コードを使わなければならない環境はあると思います。
そんな中でこれの代替になりそうなのは、 mb_ereg_replace()
ですが、これは配列渡しや参照(${0}
とかのやつです)が利用できないという弱点があります。
でも、UTF-8以外のマルチバイト文字で参照を利用したreplaceをやりたい!という方のための記事です。
説明
UTF-8以外のマルチバイト文字で参照を利用したreplaceが出来ないかというと、そんなことなかったです。 mb_ereg_replace_callback()
がありました。
この関数は第2引数に関数をとることができます。その関数の引数に、第1引数の正規表現でマッチした部分が配列として入ります。これを利用すれば参照が使えます。しかも、関数の中で使えるのでもっと柔軟な形で利用できます。
サンプルコード
<?php
// 念のため利用するエンコーディングをEUC-JPに設定しておきます。
// php.iniの設定次第では、この行は要りません。
mb_internal_encoding("EUC-JP");
// echo mb_internal_encoding() . "\n";
$text = "あいうえお かきくけこ さしすせそ たちつてと\n";
$text .= "なにぬねの はひふへほ まみむめも やいゆえよ\n";
$text .= "らりるれろ わおん\n";
// パターンは正規表現ですが、スラッシュで挟む必要はありません。
// また、少なくともEUC-JPを用いた場合、.は改行文字も含むようです。
$pattern = "([^ \n]+)([ \n])";
// 第2引数は無名関数を使うことができます。
// これにより、コールバック関数としてだけ使いたい関数があちこちに散らばるのを抑制できます。
// もちろん名前をつけた関数を利用することもできます。
// その方法はPHPの公式マニュアルを読まれるといいでしょう。
$result = mb_ereg_replace_callback(
$pattern,
function ($matches) {
if ($matches[2] === "\n") {
return $matches[1] . "," . $matches[1] . $matches[2];
} else {
return $matches[1] . "," . $matches[1] . ",";
};
},
$text
);
echo $text;
echo "\n";
echo $result;
// $resultの中身は以下です。
// あいうえお,あいうえお,かきくけこ,かきくけこ,さしすせそ,さしすせそ,たちつてと,たちつてと
// なにぬねの,なにぬねの,はひふへほ,はひふへほ,まみむめも,まみむめも,やいゆえよ,やいゆえよ
// らりるれろ,らりるれろ,わおん,わおん
echo "\n";
ここで、第2引数の関数の引数にマッチした部分が入ります。その添字と中身の関係は、通常の参照の関係と同じで、0にマッチした部分全体、1以降はサブパターンにマッチしたテキストが入ります。
まとめ
こんな感じで参照を使ったpreg_replace()の代替ができました。ちなみにpreg_replace()の方でコールバック関数を使いたいのならば、 preg_replace_callback()
があるようです。
どうでもいいですが、Qiitaって全角文字は等幅フォントじゃないのですね。この記事書いてて気付きました。
参考文献
https://www.php.net/manual/ja/function.mb-ereg-replace-callback.php
https://www.php.net/manual/ja/function.mb-ereg-replace.php
https://www.php.net/manual/ja/function.preg-replace.php
https://www.php.net/manual/ja/function.preg-replace-callback.php