The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME/НАИМЕНОВАНИЕ

perlunitut - Учебник по Юникоду в Perl

ОПИСАНИЕ

Дни простой обработки строк закончились. Установлено, что современные программы должны быть способны общаться смешанными акцентированными буквами и такими вещами, как символы евро. Это означает, что программистам нужны новые привычки. Легко программировать Юникодо-совместимое программное обеспечение, но для этого требуется дисциплина, чтобы делать это правильно.

Существует много знаний о наборах символов и кодировках текста. Вероятно, лучше всего провести целый день для их изучения, но основы могут быть изучены за минуты.

Это вообще-то не самые основы. Предполагается, что вы уже знаете разницу между байтом и символом и понимаете (и принимаете!), что существует много различных наборов символов и кодировок и, что ваша Программа должна четко знать о них. Рекомендуется для чтения Абсолютный Минимум, который Каждый Разработчик Программного Обеспечения Обязательно Должен Знать о Unicode и Наборах Символов Джоэла Спольски , оригинал на английском The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!).

Этот учебник говорит о довольно абсолютных терминах и предоставляет лишь ограниченное представление о богатстве функций обработки символов, которые Perl может предложить. Для большинства проектов этой информации, вероятно, будет достаточно.

Определения

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

Возможно, вам придется перечитать этот весь раздел несколько раз...

Юникод

Юникод— это набор символов с дополнительным окном для всех символов. Порядковый номер символа называется кодовой точкой. (Но на практике, стирается различие между кодовой точкой и символом, так что термины часто используются как синонимы.)

Есть многие, многие кодовые точки, но компьютеры работают с байтами и байт имеет окно только для только 256 значений. Юникод имеет намного больше символов, чем это, так что вам нужен метод, чтобы сделать их доступными.

Юникод кодируется с использованием нескольких конкурирующих кодировок, в которых UTF-8 является наиболее часто используемой. В кодировке Юникод несколько последующих байтов могут использоваться для хранения одной кодовой точки или просто: символа.

UTF-8

UTF-8 это Юникодная кодировка. Многие люди думают, что Юникод и UTF-8 - это одно и то же, но это не так. Есть много Юникодных кодировок, но большая часть мира стандартизирована под UTF-8.

UTF-8 рассматривает первые 128 кодовых точек, 0..127, так же, как ASCII. Она принимает только один байт на символ. Все остальные символы кодируются как два или более (до шести) байт, используя сложную схему. К счастью Perl обрабатывает это для нас, поэтому мы не должны беспокоиться об этом.

Текстовые строки (строки символов)

Текстовые строки, или символьные строки изготовлены из символов. Байт здесь не имеет значения, а только кодировка. Каждый символ это просто символ.

С текстовой строкой вы можете делать такие вещи:

    $text =~ s/foo/bar/;
    if ($string =~ /^\d+$/) { ... }
    $text = ucfirst $text;
    my $character_count = length $text;

Значение соответствующего кода символа (ord, chr) связано с Юникодной кодовой точкой.

Двоичные строки (строки байтов)

Двоичные строки, или строки байтов изготовлены из байтов. Здесь вы не имеете символов, просто байты. Все коммуникации с внешним миром (что-либо за пределами вашего текущего процесса Perl) делаются в двоичном виде.

С двоичной строкой вы могли бы сделать такие вещи, как:

    my (@length_content) = unpack "(V/a)*", $binary;
    $binary =~ s/\x00\x0F/\xFF\xF0/;  # для смелых :)
    print {$fh} $binary;
    my $byte_count = length $binary;

Кодирование (Encoding)

Кодирование (как глагол) является преобразованием от текста к двоичным данным. Для кодирования, вы должны указать целевую кодировку, например iso-8859-1 или UTF-8. Некоторые кодировки такие, как iso-8859 ("латинский") диапазон, не поддерживают полный стандарт Юникода; символы, которые не могут быть представлены теряются во время преобразования.

Декодирование (Decoding)

Декодирование является преобразованием от двоичного формата к тексту. Чтобы декодировать, вы должны знать, какая кодировка используется на этапе кодирования. И самое главное это должно быть что-то что поддается декодированию. Не будет большого смысла для декодирования изображения в формате PNG в текстовую строку.

Внутренний формат

Perl имеет внутренний формат (internal format), кодирования, который он использует для кодирования текстовых строк так, что он их может хранить в памяти. Все текстовые строки находятся в этом внутреннем формате. В самом деле текстовые строки никогда не бывают в любом другом формате!

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

Ваш новый инструментарий

Добавьте в ваш стандартный заголовок следующую строку:

    use Encode qw(encode decode);

Или, если вы ленивы, просто:

    use Encode;

Поток ввода-вывода (I/O flow) (фактические 5 минутный учебник)

Типичный поток ввода-вывода программы состоит из:

    1. Получение и декодирование (Receive and decode)
    2. Процесс (Process)
    3. Кодирование и вывод (Encode and output)

Если ваши входящие данные являются двоичными, то они и должны оставаться двоичными, вы не должны декодировать их в текстовую строку, конечно. Но, во всех остальных случаях, вы должны их декодировать.

Декодирование не может произойти надежно, если вы не знаете как закодированы данные. Если вы можете выбрать, то хорошей идеей будет сделать стандартом UTF-8.

    my $foo   = decode('UTF-8', get 'http://example.com/');
    my $bar   = decode('ISO-8859-1', readline STDIN);
    my $xyzzy = decode('Windows-1251', $cgi->param('foo'));

Обработка происходит также, как вы знали раньше. Единственное различие заключается в том, что сейчас вы используете символы вместо байт. Это очень полезно, когда вы используете такие функции, как substr, или length.

Важно понимать, что у нас нет байт в текстовой строке. Конечно Perl имеет свою внутреннюю кодировку для хранения строк в памяти, но нужно игнорировать это. Если вам нужно сделать что-нибудь байтами, то, вероятно, лучше сделать эту часть это сделать на шаге 3, только после того, как вы закодируете строки. Тогда вы знаете точно сколько байт будет в строке назначения.

Синтаксис для кодирования строк текста в двоичные строки также прост, как и для декодирования:

    $body = encode('UTF-8', $body);

Если вам необходимо знать длину строки в байтах, теперь пришло идеальное время для этого. Потому что $body теперь строка байтов и length сообщит число байт, а не число знаков. Число символов больше не известно, потому что символы существуют только в текстовых строк.

    my $byte_count = length $body;

И, если вы используете протокол, который поддерживает способ дать получателем информацию, какие кодировки символов вы использовали, пожалуйста, помогите принимающей стороне, используя эту возможность! Например, электронная почта (E-mail) и HTTP поддерживают MIME-заголовки, поэтому вы можете использовать заголовок Content-Type. Они также могут иметь Content-Length для обозначения числа байт, так что это всегда хорошая идея указать его, если это число известно.

    "Content-Type: text/plain; charset=UTF-8",
    "Content-Length: $byte_count"

РЕЗЮМЕ

Декодируйте все, что вы получаете, кодируйте все, что вы посылаете. (Если это текстовые данные.)

В и О (или ВИО) Вопросы и Ответы. (Q and A (or FAQ))

После прочтения этого документа, вы должны прочитать и perlunifaq тоже.

БЛАГОДАРНОСТИ

Спасибо Джохану Вромансу (Johan Vromans) из Squirrel Consultancy. Его замечательная речь про UTF-8 во время встречи Амстердам Perl Монгерс заинтересовала меня и позволила выяснить, как использовать кодировки символов в Perl способами, которые не ломаются легко.

Спасибо Джерарду Гуссену (Gerard Goossen) из TTY. Его презентация "UTF-8 в дикой природе" ("UTF-8 in the wild")(Голландский Perl-воркшоп 2006) вдохновила меня опубликовать мои мысли и написать этот учебник.

Спасибо людям, которые просили о такого рода вещах в нескольких Perl IRC каналах и постоянно напоминают мне о том, что требуется более простое объяснение.

Спасибо людям, которые рассмотрели этот документ для меня прежде, чем он дошел до общественности. Это: Бенджамин Смит (Benjamin Smith), Ян-Питер Корнет (Jan-Pieter Cornet), Джохан Вроманс (Johan Vromans), Лукас Май (Lukas Mai), Натан Грей (Nathan Gray).

АВТОР

Юерд Ваалбоер (Juerd Waalboer) <#####@juerd.nl>

СМОТРИТЕ ЕЩЕ

perlunifaq, perlunicode, perluniintro, Encode

ПЕРЕВОДЧИКИ

  • Николай Мишин <mi@ya.ru>