Я уже знаю, что \w
в PCRE (в частности, реализация PHP) иногда может совпадать с некоторыми символами, отличными от ASCII, в зависимости от языка системы, но как насчет [az]
?
Я бы так не подумал, но я заметил эти строки в одном из основных файлов Drupal (включая / theme.inc, упрощенный):
// To avoid illegal characters in the class, // we're removing everything disallowed. We are not using 'az' as that might leave // in certain international characters (eg German umlauts). $body_classes[] = preg_replace('![^abcdefghijklmnopqrstuvwxyz0-9-_]+!s', '', $class);
Это правда, или кто-то просто получил [az]
путать с \w
?
Короче говоря: может быть, зависит от системы, в которую развертывается приложение, зависит от того, как скомпилирован PHP, добро пожаловать в CF локализации и интернационализации.
Основной механизм PCRE учитывает локаль при определении того, что означает «az». В испанском языковом слове, – будет пойман az). Семантический смысл az – «все буквы между a и z и – это отдельное письмо на испанском языке.
Тем не менее, путь PHP слепо обрабатывает строки, поскольку коллекции байтов, а не набор кодовых точек UTF, означает, что у вас есть ситуация, когда az MIGHT соответствует акцентированному символу . Учитывая разнообразие различных систем, к которым развертывается Drupal, имеет смысл, что они будут выбирать явную информацию о допустимых символах, а не просто доверять az, чтобы делать правильные вещи.
Я также предполагаю, что существование этого регулярного выражения является результатом сообщения об ошибке, о том, что немецкие умляуты не фильтруются.
Обновление в 2014 году . Ниже представлен ответ от JimmiTh: (несмотря на некоторую документацию «confusing-to-non-pcre-core-developers»), что [az]
будет соответствовать символам abcdefghijklmnopqrstuvwxyz
в 99% случаев в предисловии. Тем не менее, разработчики рамок, как правило, испытывают раздражение относительно неопределенности в своем коде, особенно когда код использует системы (специфические для локалирования строки), которые PHP не обрабатывает так грациозно, как хотелось бы, и серверы, над которыми разработчики не имеют контроля. Хотя анонимные комментарии разработчика Drupal неверны – дело не в том, чтобы «получить [az]
путать с \w
», но вместо этого разработчик Drupal был неясным / неуверенным в том, как PCRE обрабатывает [az]
и выбирает более конкретную форму abcdefghijklmnopqrstuvwxyz
чтобы обеспечить конкретное поведение, которое они хотели.
Комментарий в коде Drupal WRONG .
Это НЕправда, что « international characters (eg German umlauts)
» могут совпадать с [az]
.
Если, например, у вас есть немецкий язык, вы можете проверить его так:
setlocale(LC_ALL, 'de_DE'); // German locale (not needed, but you never know...) echo preg_match('/^[az]+$/', 'abc') ? "yes\n" : "no\n"; echo preg_match('/^[az]+$/', "\xE4bc") ? "yes\n" : "no\n"; // äbc in ISO-8859-1 echo preg_match('/^[az]+$/', "\xC3\xA4bc") ? "yes\n" : "no\n"; // äbc in UTF-8 echo preg_match('/^[az]+$/u', "\xC3\xA4bc") ? "yes\n" : "no\n"; // w/ PCRE_UTF8
Выход (не изменится, если вы замените de_DE
на de_DE.UTF-8
):
yes no no no
Класс символов [abcdefghijklmnopqrstuvwxyz]
идентичен [az]
в обоих кодировках, которые понимает PCRE: ASCII-производный монобайт и UTF-8 (который также является ASCII-производным). В обоих этих кодировках [az]
совпадает с [\x61-\x7A]
.
Возможно, было что-то другое, когда вопрос был задан в 2009 году, но в 2014 году нет «странной конфигурации», которая может заставить PHP регулярный механизм PHP выражать [az]
как класс из более чем 26 символов (до тех пор, пока сам [az]
записывается как 5 байтов в кодировке, основанной на ASCII, конечно).
Просто добавление как к уже отличным, так и противоречивым ответам.
Документация для библиотеки PCRE всегда указывала, что «Диапазоны работают в последовательности сортировки значений символов». Это несколько расплывчато, но очень точно.
Это относится к сопоставлению индексов символов в внутренних символьных таблицах PCRE, которые могут быть настроены так, чтобы соответствовать текущему языку, используя pcre_maketables
. Эта функция строит таблицы в порядке значения char ( tolower(i)
/ toupper(i)
)
Другими словами, он не сопоставляется фактическим порядком культурной сортировки (информация о сортировке локали). В качестве примера, в то время как немецкий рассматривает ö так же, как o в сортировке словаря, ö имеет значение, которое заставляет его отображаться вне диапазона az во всех обычных кодировках символов, используемых для немецкого языка (ISO-8859-x, кодировки Unicode и т. Д.). в этом случае PCRE основывает свое определение того, находится ли ö в диапазоне [az]
на этом значении кода, а не в любом конкретном локальном порядке сортировки.
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). Вы можете сделать это, если используете нестандартный язык. Функция дает указатель на таблицы.
В то время как немецкий не будет отличаться для [az]
в любой общей кодировке символов, если бы мы имели дело с EBCDIC, например, [az]
будет включать в себя ± и ~. Конечно, EBCDIC – это кодировка одного символа, о которой я могу думать, не помещая az и AZ в непрерывную последовательность.
Если PCRE не делает какой-то магии при использовании EBCDIC (и это может быть), в то время как маловероятно, что вы включили умлауты во что угодно, кроме самой неясной среды сборки PHP или среды выполнения (используя собственное, очень специальное, сделанное на заказ определение локали) , вы можете , в случае EBCDIC, включить другие непреднамеренные символы. А для других диапазонов «сопоставление в последовательности ASCII» выглядит не совсем точно.
ETA: Я мог бы сэкономить некоторые исследования, ища собственный ответ Филиппа Хейзела на аналогичную проблему:
Другая проблема связана с диапазонами классов символов. Вы могли бы подумать, что [ak] и [xz] хорошо определены для латинских скриптов, но это не так.
Они, безусловно, хорошо определены, эквивалентны [\ x61- \ x6b] и [\ x78- \ x7a], то есть связаны с порядком кода, а не с порядком культурной сортировки.