Почему PHP preg_split разделяет ивритскую букву «נ» в UTF-8 при разбиении на «\ s»? - PullRequest
2 голосов
/ 20 ноября 2010

Это не работает, оно превращается в бред:

$foo = 'נ';
$bar = mb_convert_encoding($foo, 'UTF-8', mb_detect_encoding($foo));
print_r(preg_split('/\s/', $bar));

Массив ([0] => [1] =>)

Но это работает:

$foo = 'נ';
$bar = mb_convert_encoding($foo, 'ISO-8859-8', mb_detect_encoding($foo));
$baz = preg_split('/\s/', $bar);
echo(mb_convert_encoding($baz[0], 'UTF-8', 'ISO-8859-8'));

נ

Проблема только с буквой "נ". Он отлично работает со всеми другими ивритскими буквами. Есть ли решение для этого?

1 Ответ

7 голосов
/ 20 ноября 2010

При работе с данными UTF-8 всегда используйте модификатор u в ваших шаблонах:

/\s/u

Поскольку в противном случае шаблон не интерпретируется как UTF-8.

Как и в этом случае, символ נ (U + 05E0) кодируется с 0xD7A0 в UTF-8.И \s представляет любой символ пробела (в соответствии с PCRE ):

Символами \s являются HT (9), LF (10), FF (12),CR (13) и пробел (32).

Когда была добавлена ​​поддержка UTF-8, они также добавили специальную опцию PCRE_UCP, чтобы иметь \b, \d, \sи \w не только соответствуют символам US-ASCII, но и другим символам Unicode по своим свойствам Unicode:

По умолчанию в режиме UTF-8 символы со значениями больше 128 никогда не соответствуют \d, \s или \w и всегда соответствуют \D, \S и \W.[…] Однако, если PCRE скомпилирован с поддержкой свойств Unicode и установлена ​​опция PCRE_UCP, поведение изменяется так, чтобы свойства Unicode использовались для определения типов символов, следующим образом:

  • \d любой символ, который \p{Nd} соответствует (десятичная цифра)
  • \s любой символ, который \p{Z} соответствует, плюс HT, LF, FF, CR
  • \w любой символ, \p{L} или \p{N} совпадений, плюс подчеркивание

И этот неразрывный пробел U + 00A0 обладает свойством разделителя (\p{Z}).

Такхотя ваш паттерн не находится в режиме UTF-8, кажется, что \s соответствует 0xA0 в кодовом слове UTF-8 0xD7A0, разделяя строку в этой позиции и возвращая массив, эквивалентныйarray("\xD7", "").

И это, очевидно, ошибка, так как шаблон не в режиме UTF-8, но 0xA0 больше 0x80 (дополнительно, 0xA0 будет закодированокак 0xC2A0). ошибка # 52971 PCRE-мета-символы, не работающие с utf-8 , может быть связана с этим.

...