3

質問

PHPマニュアルには次のように記載されていますが、

「UTF-8 モードでは、値が 128 より大きい文字は、どの POSIX 文字クラスにも一致しません。」

ペルシャ数字が「UTF-8モード」で一致\dするのはなぜですか?[[:digit:]]

推敲

関連のない質問の回答者の発言では、正規表現では、 \dASCII 数字だけでなく、たとえばペルシャ数字 ( ) にも一致0する9ことが言及されてい۰ ۱ ۲ ۳ ۴ ۵ ۶ ۷ます。

上記の質問はとタグ付けされていますが、動作は PHP でも観察できます。これを念頭に置いて、次の「テスト」を作成しました。

$string = 'I have ۳ apples and 5 oranges';
preg_match_all('/\d+/', $string, $capture);

結果の配列には、のみ$captureの一致が含まれます。5

修飾子を使用しuて「UTF-8 モード」をオンにし、これを実行します。

$string = 'I have ۳ apples and 5 oranges';
preg_match_all('/\d+/u', $string, $capture);

$captureとの両方۳に一致が含まれます5

ノート

  • この質問はPHP 5.6.22(最新のもの)に関するものです
  • どちらのテストも、Cロケールを明示的に使用して実行されました。
4

1 に答える 1

3

ドキュメントが壊れているためです。残念ながら、そうである場所はそれだけではありません。

PHP は内部でPCREを使用してその機能を実装しpreg_*ます。したがって、PCRE のドキュメントはそこで信頼できます。PHP のドキュメントは PCRE のものに基づいていますが、さらに別の間違いを見つけたようです。

PCREのドキュメントで読むことができるものは次のとおりです(強調は私のものです):

デフォルトでは、値が 128 より大きい文字は、どの POSIX 文字クラスにも一致しません。ただし、PCRE_UCPオプションが に渡されるとpcre_compile()、一部のクラスが変更され、Unicode 文字プロパティが使用されます。これは、次のように、特定の POSIX クラスを他のシーケンスに置き換えることによって実現されます。

[:alnum:]  becomes  \p{Xan}
[:alpha:]  becomes  \p{L}
[:blank:]  becomes  \h
[:digit:]  becomes  \p{Nd}
[:lower:]  becomes  \p{Ll}
[:space:]  becomes  \p{Xps}
[:upper:]  becomes  \p{Lu}
[:word:]   becomes  \p{Xwd}

PHPのドキュメントをさらに掘り下げると、次のことがわかります。

あなた ( PCRE_UTF8)

この修飾子は、Perl と互換性のない PCRE の追加機能をオンにします。パターンと件名の文字列は UTF-8 として扱われます。この修飾子は、UNIX では PHP 4.1.0 以降、win32 では PHP 4.2.3 以降で利用できます。パターンと件名の UTF-8 有効性は、PHP 4.3.5 以降でチェックされます。主語が無効な場合、preg_*関数は何も一致しません。無効なパターンは level のエラーを引き起こしますE_WARNING。PHP 5.3.4 (PCRE 7.3 2007-08-28) 以降、5 オクテットと 6 オクテットの UTF-8 シーケンスは無効と見なされます。以前は有効な UTF-8 と見なされていました。

残念ながら、これは嘘です。PHPのu修飾子はPCRE_UTF8 | PCRE_UCP(UCP は Unicode Character Properties の略です) を意味します。上記のドキュメントからわかるように、PCRE_UCPフラグは、などの意味を変更するもの\dです。\wあなたのテストはそれを確認します。


補足として、ある正規表現フレーバーのプロパティを別のフレーバーから推測しないでください。常に機能するとは限りません (へー、このチャートPCRE_UCPでさえオプションを忘れていました)。

于 2016-06-06T20:26:58.853 に答える