Вопрос по ascii, php, pcre, regex – Будет ли когда-нибудь [a-z] соответствовать акцентированным символам в PREG / PCRE?

17

Я уже знаю, что\w в PCRE (особенно PHP 'Реализация) может иногда соответствовать не-ASCII-символам в зависимости от локали системы, но как насчет?[a-z]

Я бы нене думаю, но я заметил эти строки в одном из Drupal'аОсновные файлы (включает / theme.inc, упрощенный):

// To avoid illegal characters in the class,
// we're removing everything disallowed. We are not using 'a-z' as that might leave
// in certain international characters (e.g. German umlauts).
$body_classes[] = preg_replace('![^abcdefghijklmnopqrstuvwxyz0-9-_]+!s', '', $class);

Это правда, или кто-то просто получил[a-z] путать с?\w

Ваш Ответ

3   ответа
13

Короче говоря: возможно, зависит от системы, в которой развернуто приложение, зависит от того, как был скомпилирован PHP, добро пожаловать в CF локализации и интернационализации.

Базовый механизм PCRE учитывает локаль при определении того, что "A-Z» средства. В испанском языке, - будет пойман на а-я). Семантическое значение а-я "все буквы между a и z и - это отдельное письмо на испанском языке.

Однако то, как PHP слепо обрабатывает строки как наборы байтов, а не набор кодовых точек UTF, означает, что у вас есть ситуация, когда a-z МОЖЕТ соответствовать символу с акцентом, Учитывая разнообразие систем, в которых развертывается Drupal, имеет смысл, что они решат явно указывать разрешенные символы, а не просто доверять a-z, чтобы делать правильные вещи.

d также предположить, что существование этого регулярного выражения является результатом сообщения об ошибке о том, что немецкие умлауты не фильтруются.

Обновление в 2014 году: ЗаJimmiTh»ответ нижеПохоже (несмотря на некоторые "запутанные к не-PCRE-Core-разработчики» документация) что[a-z] будет соответствовать только персонажамabcdefghijklmnopqrstuvwxyz пресловутый 99% времени. Это сказал -разработчики фреймворков имеют тенденцию раздражаться из-за неопределенности в своем коде, особенно когда код опирается на системы (специфичные для локали строки), которых PHP не делаетсправиться так же изящно, как и тыМне нравится, и серверы разработчики не имеют никакого контроля. В то время как анонимный разработчик Drupalкомментарии неверны - это не былоэто вопрос "получение[a-z] путать с\w, но вместо этого разработчик Drupal неясен / не уверен в том, как обрабатывается PCRE[a-z]и выбрав более конкретную формуabcdefghijklmnopqrstuvwxyz чтобы обеспечить конкретное поведение, которое они хотели.

Действительно ли это было правдой в 2009 году? Walter Tross
@WalterTross Сегодня всё так же верно, как и тогда. Это'никогда не о чемэто было / это обычноо том, что МОЖЕТ произойти с какой-то странной конфигурацией, и убедиться, что ваш коддостаточно надежный, чтобы справиться с этим. Alan Storm
@AlanStorm, вы можете предоставить такую странную конфигурацию? Я'Я уверен, что нет! Walter Tross
7

Просто дополнение к обоим, уже превосходным, хотя и противоречивым, ответам.

В документации для библиотеки PCRE всегда указывалось, чтоДиапазоны работают в порядке сопоставления значений символов, Что несколько расплывчато, но все же очень точно.

Это относится к сопоставлениюиндекс персонажей в PCRE 'внутренние таблицы символов, которые можно настроить в соответствии с текущей локалью, используяpcre_maketables, Эта функция строит таблицы в порядке значения символа (/)tolower(i)toupper(i)

Другими словами, это не• сопоставлять по фактическому культурному порядку сортировки (информация о сопоставлении локали). Как пример, пока немецкий трактует ö так же, как о в словаре сопоставления, ö имеет значение, которое заставляет его появляться за пределами диапазона a-z во всех кодировках общих символов, используемых для немецкого языка (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) локаль isn 'язык POSIX / C, среда выполненияs POSIX / C locale 'порядок символов s используется. В противном случае используются таблицы PCRE по умолчанию, которые создаютсяpcre_maketables) когда PCRE компилируется -на основе компиляторас языком:

Эта функция создает набор таблиц символов для значений символов меньше 256. Они могут быть переданы в pcre_compile () для переопределения PCRE 'Внутренние встроенные таблицы (которые были созданы pcre_maketables () при компиляции PCRE). Возможно, вы захотите сделать это, если вы используете нестандартную локаль. Функция выдает указатель на таблицы.

В то время как немецкий нене должно быть другим для[a-z] в любой обычной кодировке символов, если мы имеем дело, например, с EBCDIC,[a-z] будет включать в себя ± и ~. Конечно, EBCDIC - это единственная символьная кодировка, о которой я неt поместите a-z и A-Z в непрерывной последовательности.

Если PCRE не использует магию при использовании EBCDIC (и это возможно), в то время какочень маловероятно, что выЕсли вы будете включать умлауты во что угодно, кроме самой непонятной среды сборки PHP или среды выполнения (используя ваше собственное, очень специальное, индивидуальное определение локали), выможет быть, в случае EBCDIC, включите другие непреднамеренные символы. А для других диапазоновсопоставлено в последовательности ASCII Безразлично»кажется совершенно точным.

ETA: Я мог бы спасти некоторые исследования, ища Филиппа Хейзелаs собственный ответ на аналогичную проблему:

Другая проблема связана с диапазонами классов персонажей. Можно подумать, что [a-k] и [x-z] хорошо определены для латинских скриптов, но этодело не в этом.

Они, безусловно, четко определены и эквивалентны [\ x61- \ x6b] и [\ x78- \ x7a], то есть относятся к порядку кодов, а не к порядку сортировки по культуре.

Странная вещь с strcmp (3) в том, что он возвращает эквивалент false, когда строки совпадают. Итак, pcre_maketables вызывается для чего угодно, НО языка Си. Melvyn
@WalterTross, тыверно, они будут запускать COBOL, который похож на PHP 60-х годов. Chris Wesseling
pcre_maketables () строит только следующие таблицы: таблица нижнего регистра, таблица переключения регистра, таблицы классов символов, таблица типов символов. Это нене иметь дело с сопоставлениями. Что касается EBCDIC, если кто-то покажет мне машину EBCDIC, которая на самом деле работает на PHP, где PCRE в PHP интерпретирует[a-z] как[\x81-\xA9], Я подчиняюсь. Walter Tross
Спасибо, исправлено. :-) Несмотря на то, что в последние 15 лет я мало занимался Си, я, кажется, вспомнил, что посмотрел его, чтобы быть уверенным, а затем все же смог написать неправильное объяснение. К счастью, это ничего не меняет, поскольку эта часть является просто тем, что уже предполагалось - что PHP в некоторых случаях меняет язык PCRE при компиляции выражений. Который неЭто не имеет значения, потому что есть немного, если таковые имеются, кодировки локали, которые изменяют значения кода a-z. JimmiTh
Да. ОтсюдаДругими словами, это неt сопоставлять по фактическому культурному порядку сортировки (информация о сопоставлении локали) ", Весь смысл ответаявляется что это не такне иметь дело с сопоставлениями. JimmiTh
10

комментарий в Друпалес кодомНЕПРАВИЛЬНО.

ЭтоНЕ правда что ""international characters (e.g. German umlauts) может совпадать.[a-z]

Если, например, у вас есть немецкий язык, вы можете проверить его следующим образом:

setlocale(LC_ALL, 'de_DE'); // German locale (not needed, but you never know...)
echo preg_match('/^[a-z]+$/', 'abc') ? "yes\n" : "no\n";
echo preg_match('/^[a-z]+$/', "\xE4bc") ? "yes\n" : "no\n"; // äbc in ISO-8859-1
echo preg_match('/^[a-z]+$/',  "\xC3\xA4bc") ? "yes\n" : "no\n"; // äbc in UTF-8
echo preg_match('/^[a-z]+$/u', "\xC3\xA4bc") ? "yes\n" : "no\n"; // w/ PCRE_UTF8

Выход (не изменится, если вы заменитеde_DE сde_DE.UTF-8):

yes
no
no
no

Класс персонажа[abcdefghijklmnopqrstuvwxyz] идентично[a-z] в обоих кодировках PCRE понимает: монобайт, полученный из ASCII, и UTF-8 (который также является производным от ASCII). В обоих этих кодировках[a-z] такой же как .[\x61-\x7A]

Возможно, все было иначе, когда вопрос задавался в 2009 году, но в 2014 году его нет »странная конфигурация что может сделать PHPS PCRE регулярное выражение двигателя интерпретировать[a-z] как класс из более чем 26 символов (до тех пор, пока[a-z] само по себе записывается как 5 байтов в ASCII-производной кодировке, конечно).

Ты прибил это +1 HamZa
Что происходит, когда код файла PHP изменился? Alan Storm
@AlanStorm: если кодировка ISO-8859- *, UTF-8 или любая кодовая страница Windows, которая содержит строчные буквы английского алфавита: ничего. С другой стороны, похоже, что PHP может быть скомпилирован для чтения, например, исходного кода UTF-16 (я нене знаю, что) Я неу меня нет сил, чтобы попробовать это. Если у кого-то есть, они могут опубликовать свои выводы здесь. Walter Tross

Похожие вопросы