Несмотря на руководство по PHP:
Почему персидские цифры совпадают \d
или же [[:digit:]]
в «режиме UTF-8»?
В замечании ответчика в несвязанный вопрос упоминается, что в регулярных выражениях \d
не только соответствует ASCII цифрам 0
через 9
но также, например, персидские цифры (۰ ۱ ۲ ۳ ۴ ۵ ۶ ۷
).
Вышеупомянутый вопрос помечен Джава но поведение можно наблюдать и в PHP. Имея это в виду, я написал следующий «тест»:
$string = 'I have ۳ apples and 5 oranges';
preg_match_all('/\d+/', $string, $capture);
Полученный массив $capture
содержит совпадение на 5
только.
С использованием u
Модификатор для включения «UTF-8 mode» и запуска этого:
$string = 'I have ۳ apples and 5 oranges';
preg_match_all('/\d+/u', $string, $capture);
результаты в $capture
содержащие совпадения на обоих ۳
а также 5
,
C
локали.Потому что документация не работает. И это, к сожалению, не единственное место, где это так.
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
)Этот модификатор включает дополнительные функции PCRE, несовместимые с Perl. Шаблонные и предметные строки рассматриваются как UTF-8. Этот модификатор доступен из PHP 4.1.0 или выше в Unix и из PHP 4.2.3 в win32. UTF-8 валидность шаблона и предмета проверена начиная с PHP 4.3.5. Недопустимый предмет вызовет
preg_*
функция ничего не соответствует; неверный паттерн вызовет ошибку уровняE_WARNING
, Последовательности UTF-8 с пятью и шестью октетами считаются недействительными начиная с PHP 5.3.4 (соответственно PCRE 7.3 2007-08-28); ранее они считались действительными UTF-8.
Это, к сожалению, ложь. u
модификатор в PHP означает PCRE_UTF8 | PCRE_UCP
(UCP обозначает Свойства символов Юникода). PCRE_UCP
флаг это тот, который меняет смысл \d
, \w
и тому подобное, как вы можете видеть из документов выше. Ваши тесты подтверждают это.
В качестве примечания, не делайте свойства одного вкуса регулярного выражения из другого. Это не всегда работает (хе, даже этот график забыл о PCRE_UCP
опция).
Других решений пока нет …