2012-05-30 5 views
9

Прежде чем кто будет говорит мне RTFM, я должен сказать, - я выкопал через:Внутренности Perl Unicode - связывайтесь с utf8

Итак, основной код:

use 5.014;   #getting 'unicode_strings' feature 
use uni::perl;  #turning on many utf8 things 
use Unicode::Normalize qw(NFD NFC); 
use warnings; 
while(<>) { 
    chomp; 
    my $data = NFD($_); 
    say "OK" if utf8::is_utf8($data); 
} 

На данный момент, отutf8 кодируются STDIN я получил правильный юникода строку в $data, например, «\ w» будет соответствовать multibyte [\p{Alphabetic}\p{Decimal_Number}\p{Letter_Number}] (может быть, что-то еще). Это нормально и работает.

AFAIK $data делает не содержат utf8, но строка в формате perl's internal Unicode.

Теперь вопросы:

  • Как я могу убедиться (проверить это), что любой $other_data содержит допустимую строку Unicode?
  • С какой целью является utf8 :: is_utf8 ($ data)? Вся прагма для меня - загадка.

Я понимаю, что use utf8; только для того, чтобы сказать Perl, что мой исходный код находится в utf8 (так делают подобные вещи, как, когда мой сценарий начинается с флагом BOM - для BigEndian) - с точки Perl зрения, мой исходный код похож на внешний файл - и Perl должен знать, в какой кодировке он ...

В приведенном выше примере utf8::is_utf8($data) будет печатать OK - но я не понимаю ПОЧЕМУ.

Внутренне Perl не использует utf8, поэтому мой utf8 данных файл преобразуется во внутренний Unicode в Perl, так почему же utf8::is_utf8($data) возвращение верно для $data, который не в формате utf8? Или это неправильно, и функция должна быть названа uni :: is_unicode ($ data) ???

Заранее благодарим за разъяснения.

Ps: d @ Брайан Фой - да, я до сих пор не имеют Эффективное Perl Программирование книги - Я понимаю, - я обещаю :)/шучу/

ответ

7

is_utf8 возвращает информацию о которой внутренняя память формат использовался, период.

  • Это не связано со значением строки (хотя некоторые строки могут храниться только в одном из двух форматов).
  • Это не связано с тем, была ли строка декодирована или нет.
  • Это не связано с тем, содержит ли строка что-то, что было закодировано с использованием UTF-8 или нет.
  • Это не проверка действительности.

Теперь на ваши вопросы.


Вся прагма utf8 является для меня загадкой.

use utf8; сообщает perl ваш исходный код кодируется с использованием UTF-8. Если вы этого не скажете, perl эффективно предполагает, что это iso-8859-1 (как побочный эффект внутренних механизмов).

Функции в пространстве имен utf8 :: не связаны с прагмой и служат для различных целей.

  • utf8::encode и utf8::decode: Полезные функции кодирования и декодирования. Подобно Encode encode_utf8 и decode_utf8, но они работают на месте.
  • utf8::upgrade и utf8::downgrade: Редко используется, но полезно для работы с ошибками в модулях XS. Подробнее об этом ниже.
  • utf8::is_utf8: Я не знаю, почему кто-то когда-либо использовал это.

Как я могу гарантировать (проверить это), чем любой $ other_data содержит допустимую строку Юникода?

Что для вас означает «действительная строка Unicode»? Unicode имеет разные определения, действующие для разных обстоятельств.


С какой целью является utf8 :: is_utf8 ($ data)?

Отладка. Он заглядывает в кишки Перла.


В приведенном выше примере utf8 :: is_utf8 ($ data) будет печатать OK - но не понимает ПОЧЕМУ.

Поскольку NFD выбрал для возврата скаляр, содержащий строку в формате UTF8 = 1.

Perl, имеет два формата для хранения строк:

  • UTF8 = 0 может хранить последовательность 8-битовых значений.
  • UTF8 = 1 может хранить последовательность 72-битовых значений (хотя практически ограничено 32 или 64 бита.)

Первый формат использует меньше памяти и быстрее, когда речь идет о доступе к определенной позиции в строка, но она ограничена тем, что она может содержать. (Например, он не может хранить коды кода Unicode, так как они требуют 21 бит.) Perl может свободно переключаться между ними.

use utf8; 
use feature qw(say); 

my $d = my $u = "abcdé"; 
utf8::downgrade($d); # Switch to using the UTF8=0 format for $d. 
utf8::upgrade($u); # Switch to using the UTF8=1 format for $u. 

say utf8::is_utf8($d) ?1:0; # 0 
say utf8::is_utf8($u) ?1:0; # 1 
say $d eq $u   ?1:0; # 1 

Обычно не нужно беспокоиться об этом, но есть неисправные модули. Есть даже глючные углы Perl, оставшиеся, несмотря на use feature qw(unicode_strings);. Можно использовать utf8::upgrade и utf8::downgrade для изменения формата скаляра на ожидаемый функцией XS.


Или это пропущенное имя и функция должна называться uni :: is_unicode ($ data) ???

Это не лучше. Perl не знает, является ли строка строкой Unicode или нет. Если вам нужно отслеживать это, вам нужно отследить его самостоятельно.

Строки в формате UTF8 = 0 могут содержать кодовые обозначения Unicode.

my $s = "abc"; # U+0041,0042,0043 

Строки в формате UTF8 = 1 могут содержать значения, которые не являются кодами Unicode.

my $s = pack('W*', @temperature_measurements); 
+0

Пропустил ли я что-нибудь? – ikegami

+0

@ cajwine, Некоторые грамматические ошибки в вашем ответе затрудняют понимание. Я добавил немного к самому началу моего сообщения, которое должно подчеркнуть, что важно. – ikegami

+0

@ cajwine, я добавил к своему ответу: «Вся прагма utf8 для меня загадка.«поскольку вы, очевидно, не говорите о« использовании utf8; ». – ikegami

5

Как я могу гарантировать (проверить это), чем любой $ other_data содержит допустимую строку Юникода?

Вы не можете определить ex post facto, имеет ли строка семантику символов или семантику байтов. Perl не отслеживает это для вас. Вы должны отслеживать это путем тщательного программирования: кодировать и декодировать на границах; :rawlayer для байтовой семантики, :encoding(foo) для символа семантики. Используйте naming conventions для своих переменных и функций, чтобы четко различать семантику и сделать неправильный код. смотрите неправильно.

С какой целью является utf8 :: is_utf8 ($ data)?

Это говорит о наличии флага SvUTF8, не более того. Это почти совершенно бесполезно для большинства разработчиков, потому что это внутренняя вещь. Флаг не означает, что строка имеет семантику символов, ее отсутствие не означает, что строка имеет байтовую семантику.

Вся прагма utf8 является для меня загадкой.

Наверное, потому что это сверхдокументировано и поэтому путает. Большинство разработчиков могут прекратить чтение после того, как говорится, что его цель - включить литералы Unicode в исходном коде.

В приведенном выше примере utf8 :: is_utf8 ($ data) будет печатать OK - но не понимает ПОЧЕМУ.

Из-за uni :: perl, который разрешает use open qw(:utf8 :std);. Любой вход, считываемый из STDIN с <>, будет декодирован. После этого шаг нормализации не меняет этого.

+0

Он использует формат, похожий на UTF-8, для хранения этих 72-битных значений. Он называется «utf8» и используется только Perl сам по себе. См. «Perl -MDevel :: Peek -e'Dump (« \ x {2660} »);' ' – ikegami

+0

Что касается того, почему что-то, что было декодировано, все еще закодировано, потому что вещи всегда должны быть закодированы на некотором уровне потому что вещи всегда должны храниться в байтах. Perl представляет вам числа и строки, но внутри, это IEEE floats и utf8 строки. – ikegami

+0

и целые числа ... – ysth