矛盾している場合でも、すでに優れた両方の回答に追加するだけです。
PCRE ライブラリのドキュメントには、「範囲は文字値の照合シーケンスで動作する」と常に記載されています。これはやや曖昧ですが、非常に正確です。
を使用して現在のロケールに一致するように設定できる、PCRE の内部文字テーブル内の文字のインデックスによる照合を指しますpcre_maketables
。その関数は、char 値 ( tolower(i)
/ toupper(i)
)の順にテーブルを構築します。
つまり、実際の文化的な並べ替え順序 (ロケール照合情報) では照合されません。例として、ドイツ語は ö を辞書照合で o と同じように扱いますが、ö は、ドイツ語で使用されるすべての一般的な文字エンコーディング (ISO-8859-x、Unicode エンコーディングなど) で az 範囲外に表示される値を持ちます。この場合、PCRE は、[a-z]
実際のロケール定義の並べ替え順序ではなく、ö がそのコード値の範囲内にあるかどうかを判断します。
PHP はほとんどの場合、 PCRE のドキュメントを docsに逐語的にコピーしています。ただし、実際には、上記のステートメントを「範囲はASCII照合シーケンスで動作する」に変更するのに苦労しました。この声明は、少なくとも 2004 年以降はドキュメントに含まれています。
上記にもかかわらず、それが本当かどうかはよくわかりません。
少なくとも、すべての場合ではありません。
PHPが行う1つの呼び出しpcre_maketables
... PHPソースから:
#if HAVE_SETLOCALE
if (strcmp(locale, "C"))
tables = pcre_maketables();
#endif
つまり、PHP がコンパイルされる環境がsetlocale
あり、(LC_CTYPE) ロケールが POSIX/C ロケールでない場合、実行環境の POSIX/C ロケールの文字順序が使用されます。それ以外の場合は、コンパイラのロケールに基づいて、pcre_maketables
PCRE のコンパイル時に(によって) 生成されるデフォルトの PCRE テーブルが使用されます。
この関数は、256 未満の文字値の一連の文字テーブルを作成します。これらを pcre_compile() に渡して、PCRE の内部の組み込みテーブル (PCRE のコンパイル時に pcre_maketables() によって作成されたもの) をオーバーライドできます。非標準のロケールを使用している場合は、これを行うことができます。この関数は、テーブルへのポインターを生成します。
ドイツ語は[a-z]
どの一般的な文字エンコーディングでも違いはありませんが、たとえば、EBCDIC を扱っている場合は[a-z]
、± と ~ が含まれます。確かに、EBCDIC は、az と AZ を連続したシーケンスに配置しない、私が考えることができる唯一の文字エンコーディングです。
PCRE が EBCDIC を使用するときに何らかの魔法を行わない限り (そしてそうなる可能性があります)、最もあいまいな PHP ビルドまたはランタイム環境 (独自の非常に特別なカスタムメイドのロケール定義を使用する) 以外にウムラウトを含めることはほとんどありません。 、EBCDIC の場合は、他の意図しない文字を含めることができます。また、他の範囲については、「ASCII シーケンスで照合」は完全に正確ではないようです。
ETA:同様の懸念に対する Philip Hazel 自身の回答を探すことで、調査を節約できたかもしれません。
別の問題は、文字クラスの範囲にあります。[ak] と [xz] はラテン文字用に適切に定義されていると思われるかもしれませんが、そうではありません。
それらは確かに明確に定義されており、[\x61-\x6b] および [\x78-\x7a] と同等です。つまり、文化的な並べ替え順序ではなく、コードの順序に関連しています。