Просто дополнение к обоим и без того превосходным, хотя и противоречивым, ответам.
В документации к библиотеке PCRE всегда указывалось, что «Диапазоны работают в порядке сопоставления значений символов». Что несколько расплывчато, но все же очень точно.
Это относится к сортировке по индексу символов во внутренних таблицах символов PCRE, которые можно настроить в соответствии с текущей локалью, используя pcre_maketables
. Эта функция строит таблицы в порядке значения символа (tolower(i)
/ toupper(i)
)
Другими словами, он не сопоставляется по фактическому культурному порядку сортировки (информация о сопоставлении локали). Например, в то время как немецкий язык рассматривает ö так же, как o в сопоставлении словаря, ö имеет значение, которое заставляет его появляться вне диапазона az во всех общих кодировках символов, используемых для немецкого языка (ISO-8859-x, кодировки unicode и т. Д.) в этом случае PCRE будет основывать свое определение того, находится ли ö в диапазоне [a-z]
на этом значении кода, а не на каком-либо действительном порядке сортировки, определяемом языковым стандартом.
PHP в основном скопировал документацию PCRE дословно в своих документах . Тем не менее, они на самом деле приложили много усилий, изменив вышеприведенное утверждение на «Диапазоны работают в последовательности сортировки ASCII». Это заявление было в документах по крайней мере с 2004 года.
Несмотря на вышесказанное, я не совсем уверен, что это правда.
Ну, не во всех случаях, по крайней мере.
Один вызов PHP делает на pcre_maketables
... Из источника PHP :
#if HAVE_SETLOCALE
if (strcmp(locale, "C"))
tables = pcre_maketables();
#endif
Другими словами, если среда, для которой компилируется PHP, имеет setlocale
и , языковой стандарт (LC_CTYPE) не является языковым стандартом POSIX / C, порядок символов языкового стандарта POSIX / C среды выполнения - используемый. В противном случае используются таблицы PCRE по умолчанию - которые генерируются (pcre_maketables
) при компиляции PCRE - на основе локали компилятора :
Эта функция создает набор таблиц символов для значений символов меньше 256. Они могут быть переданы в pcre_compile () для переопределения внутренних встроенных таблиц PCRE (которые были созданы pcre_maketables () при компиляции PCRE). Возможно, вы захотите сделать это, если вы используете нестандартную локаль. Функция выдает указатель на таблицы.
Хотя немецкий не будет отличаться для [a-z]
в любой обычной кодировке символов, если бы мы, например, имели дело с EBCDIC, [a-z]
включал бы ± и ~. Конечно, EBCDIC - это единственная символьная кодировка, которая не помещает a-z и A-Z в непрерывную последовательность.
Если PCRE не использует магию при использовании EBCDIC (и это возможно), в то время как весьма маловероятно, что вы будете включать умлауты во что-либо, кроме самой непонятной среды сборки или выполнения PHP (используя свою собственную, очень особенную, изготовленную на заказ определение локали), вы могли бы , в случае EBCDIC, включать другие непреднамеренные символы. А для других диапазонов «сопоставление в последовательности ASCII» не совсем точно.
ETA: Я мог бы спасти какое-то исследование, посмотрев на собственный ответ Филиппа Хейзела на аналогичную проблему:
Другая проблема связана с диапазонами классов символов. Можно подумать, что [a-k] и [x-z] хорошо определены для латинских скриптов, но это не так.
Они, безусловно, четко определены и эквивалентны [\ x61- \ x6b] и [\ x78- \ x7a], то есть относятся к порядку кодов, а не к порядку сортировки по культуре.