【PHP】preg系で日本語を使う場合、パターン修飾子『u』は不可欠

結論 (2018年8月2日現在)

検索対象にマルチバイト文字が含まれていても、抽出したい文字に含まれていなければ不要。

しかし安全のため、どんな時でもパターン修飾子"u"を付けるべき。

実験


<?php
$subject = '漢字abcdひらがな한글Кириллица';
$patterns = array(
'/\w+/',
'/\w+/u',
'/[a-z]+/',
'/[a-z]+/u',
'/[あ-ん]+/',
'/[あ-ん]+/u'
);

$v = phpversion();
echo "PHP: {$v}<br>";
echo "検索対象: {$subject}<br><br>";

foreach ($patterns as $pattern) {
echo "{$pattern}: ";
preg_match($pattern, $subject, $matches);
print_r($matches[0]);
echo '<br>';
}


PHP5.6.3, PHP7.2.2での結果は以下のとおりです。

検索対象の文字列
漢字abcdひらがな한글Кириллица

各パターンの結果
パターン結果
/\w+/abcd
/\w+/u漢字abcdひらがな한글Кириллица
/[a-z]+/abcd
/[a-z]+/uabcd
/[あ-ん]+/��
※ 文字化けしている
/[あ-ん]+/uひらがな


解説

PHPの"preg_*"系の関数の正規表現(PCRE)で日本語などのマルチバイト文字を扱う場合、PHPのバージョンによって微妙に結果が変わります。


この記事の公開当時はパターン修飾子"u"が必須でした。
しかしPHP5.6では、検索対象の中に日本語が含まれているが正規表現の中で日本語は使わない、という場合ならばパターン修飾子"u"は必要ないようです。


また、文字クラス"\w"は、以前はアルファベットと数字のみにマッチしていました。
つまり『[0-9a-zA-Z]』です。
しかしPHP5.6でパターン修飾子"u"を付けた場合は、単語を構成する文字ならば漢字でも平仮名でもハングルでもキリル文字でもマッチするようです。
これはおそらくv5.3.4での変更によるものと思われます。


参照: http://php.net/ChangeLog-5.php#5.3.4


PCRE extension:
Fixed bug #52971 (PCRE-Meta-Characters not working with utf-8). (Felipe)