«Слово» персонажей из набора Юникод - PullRequest
1 голос
/ 11 июля 2011

Мне было интересно, как PCRE обнаруживает символы слова на любом языке. Я тестировал эту строку:

"間違つ"

Файл php кодируется как UTF-8 и правильно помечен с помощью Charset = UTF-8 в теге типа контента.

<?php

$string="\xE9\x96\x93\xE9\x81\x95\xE3\x81\xA4"; //Bytestream from "間違つ" 
$string=preg_replace('/\w/','\w',$string);
echo $string;
echo "<br>";


$byte="\xE9"; //I've tried with each byte separately to find word characters
if(preg_match('/\w/',$byte)){
    echo "$byte is a word";
    }
else{ 
    echo "$byte is not a word";
    }
?>

"\xE9" "\xE9" "\xE3" из всех байтов являются словами.

Это дисплей:

Displayed

Я знаю, почему появляются символы. Декодер использует символ замены Unicode, кодовую точку FFFD, как декодирование неверной последовательности UTF-8, а не прекращение обработки текста. Существуют недопустимые последовательности, поскольку один «символ слова» заменяется заменой '\w' и затем он сломал «байтовую безопасность», чтобы показать.

Итак, вопросы:

почему эти символы сопоставляются как слова, если они не являются допустимыми последовательностями UTF-8?

Как узнать, какие символы действительно являются символами слов во всем наборе Unicode?

Ответы [ 2 ]

2 голосов
/ 11 июля 2011

Вы должны установить u -Flag , иначе он интерпретируется как строка ISO-8859-1.

Следующий скрипт показывает, какие символы \w соответствуют без флага u:

header("Content-Type: text/plain");
$i = 255;
while($i--)
{
    preg_match('/\w/S', chr($i), $m);
    printf("%' 1s \x%s\n", $m[ 0 ], strtoupper(bin2hex($m[ 0 ])));
}

Только [a-zA-Z] соответствуют \w, если установлен u -Flag:

// added 'A' at the beginning and 'B' at the end
preg_match_all('/\w/u', "A\xE9\x96\x93\xE9\x81\x95\xE3\x81\xA4B", $m);
print_r($m);

Внимание : Если присутствует флаг u -Flag, preg_ * автоматически прекратит синтаксический анализ строки, если она содержит символы не в Юникоде (например, \ x80- \ xFF).

2 голосов
/ 11 июля 2011

Я считаю, что ваш движок регулярных выражений интерпретирует ваш поток байтов так, как если бы они были закодированы в ISO Latin-1 (а это не так). В ISO Latin-1,

  • E3 - ЛАТИНСКОЕ МАЛЕНЬКОЕ ПИСЬМО А С TILDE
  • E9 - ЛАТИНСКОЕ МАЛЕНЬКОЕ ПИСЬМО Е С ОСТРЫМ

, которые являются символами "слова", но

, которые не являются символами слова.

Вы можете установить модификатор /u в регулярном выражении, чтобы он работал с UTF-8, а не с Latin-1. См. Руководство PHP по модификаторам шаблонов .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...