PHPでマルチバイト文字列を扱うとき、私たちはしばしば、より良いユニコードの互換性を得るためにMBSTring拡張機能に依存しています。特に、 MB_EREG_REPLACEとMB_EREGI_REPLACEは、多バイトに優しい定期的な交換機能であると主張されています。多くの開発者は、PCREのような\ p {han}などのユニコード属性を認識できると誤って信じているため、漢字の正確なマッチングを実現しています。
残念ながら、このアイデアは間違っています。
まず第一に、 MB_EREG_REPLACEとMB_EREG_REPLACEはOnigurumaに基づいて通常のエンジンを使用していることは明らかですが、使用する構文パターンはPerl互換性のある正規表現(PCRE)ではありませんが、古い限られた機能POSIXバリアントです。 Oniguruma自体はUnicode属性のマッチングをサポートしていますが、前提は、適切なモードを有効にする必要があることです(たとえば、 preg_matchはphp 7.3+で\ p {han}をサポートしています)。
典型的な誤解コードの例を見てみましょう。
$text = 'これはです test コンテンツ 123';
$result = mb_eregi_replace('\p{Han}+', '', $text);
echo $result;
このスクリプトは漢字を削除し、英語と数字を保存すると思いますか?実際、そうしません。 MB_EREGI_REPLACEは、\ Pを通常のバックスラッシュと文字Pとして扱い、 {han}は特別なセマンティクスとしてまったく認識されません。これにより、正規表現がまったく無効になり、漢字と一致しません。
Unicodeプロパティのサポートを実装するには、これを行う正しい方法は、phpがUnicodeモードを使用して文字列を解釈できるように、 preg_replaceを使用してU修飾子を追加することです。
正しい例を見てみましょう:
$text = 'これはです test コンテンツ 123';
$result = preg_replace('/\p{Han}+/u', '', $text);
echo $result;
出力:
test 123
これが私たちが本当に望んでいる効果です。
多くの開発者がMB_EREGI_REPLACEに「マルチバイトのサポート」があるという説明を見ると、自然にUnicode属性、特に中国のコミュニティの多くの古いチュートリアルや記事が明確になっていないと自然に考えています。たとえば、 MB_EREGI_REPLACE \ P {HAN}を検索すると、曖昧な説明や時代遅れの説明が見つかるかもしれません。
さらに、プロジェクトがMB_EREGI_REPLACEを使用して規則性を処理することに慣れている場合、中国語やその他のユニコード文字セットを扱うときに立ち往生する可能性が非常に高く、特にテキストクリーニングやデータ抽出などのタスクでは、データフィルタリングまたは論理エラーが不完全になります。
正直に言うと、あなたはそれを使用するのをやめたほうがいいです。ただし、互換性のニーズに使用する必要がある場合は、漢字の範囲エンコーディングを使用することを検討できます。
$text = 'これはです test コンテンツ 123';
$result = mb_eregi_replace('[1つ-薔薇]+', '', $text);
echo $result;
このアプローチは十分に正確ではありませんが(たとえば、すべての漢字の拡張機能と一致することはできません)、 \ p {han}を盲目的に使用するよりも少なくとも信頼性が高くなります。さらに進むと、複数の漢字間隔を手動でリストして精度を向上させることができますが、最終的には症状を治療しますが、根本的な原因は治療しません。
より良いアプローチは、 preg_replaceに完全に頼り、 mbstring.func_overloadまたは適切なマルチバイトサポートポリシーが有効になっていることを確認することです。これにより、PCREのパワーが最大化されます。
mb_eregi_replace( '\ p {han}'、...)を誤用しないでください。 \ p {}の構文はまったく認識されません。 Unicodeプロパティを処理する必要がある場合、唯一の信頼できるオプションは、 Uモディファイアを使用したpreg_replaceです。この誤解は長年にわたって多くのPHP開発者に問題を抱えており、ソースを修正する時が来ました。