perlunitut
СОДЕРЖАНИЕ
- ИМЯ
- ОПИСАНИЕ
- РЕЗЮМЕ
- Вопросы и ответы (или часто задаваемые вопросы)
- БЛАГОДАРНОСТИ
- АВТОР
- СМОТРИТЕ ТАКЖЕ
ИМЯ
perlunitut - Руководство по Unicode для Perl
ОПИСАНИЕ
Эпоха простого обращения со строками прошла. Сейчас совершенно ясно, что современные программы должны уметь обрабатывать забавные символы с диакритическими знаками и такие вещи, как символ евро. Это означает, что программисты должны приобрести новые привычки. Программирование Unicode-совместимого ПО несложно, но требует дисциплины для качественной работы.
Существует множество тонкостей относительно наборов символов и кодировок текста. Вероятно, лучше потратить целый день на изучение всего этого, но основы можно освоить за несколько минут.
Однако это не самые элементарные основы. Предполагается, что вы уже знаете разницу между байтами и символами и понимаете (и принимаете!), что существует множество различных наборов символов и кодировок, а ваша программа должна явно указывать их. Рекомендуется к прочтению статья «Абсолютно необходимый минимум, который каждый разработчик ПО должен знать о Unicode и наборах символов (нет оправданий!)» Джоэла Сполского по адресу http://joelonsoftware.com/articles/Unicode.html.
В этом руководстве используется довольно категоричный подход и предоставляется лишь ограниченный обзор богатого функционала Perl, связанного со строками символов. Для большинства проектов этой информации, вероятно, будет достаточно.
Определения
Сначала важно уточнить некоторые моменты. Это самая важная часть данного руководства. Эта информация может противоречить некоторым сведениям, найденным в Интернете, но это в основном потому, что много источников неверны.
Возможно, вам придётся несколько раз перечитать этот раздел...
Unicode
Unicode — это набор символов, способный вместить множество символов. Порядковый номер символа называется кодовой точкой. (Однако на практике различие между кодовой точкой и символом размывается, поэтому эти термины часто используются как взаимозаменяемые.)
Существует множество кодовых точек, но компьютеры работают с байтами, а байт может хранить только 256 значений. Unicode содержит намного больше символов, поэтому нужен способ сделать их доступными.
Unicode кодируется с помощью нескольких конкурирующих кодировок, наиболее распространённой из которых является UTF-8. В кодировке Unicode для хранения одной кодовой точки (или, проще говоря, символа) могут использоваться несколько последующих байтов.
UTF-8
UTF-8 — это кодировка Unicode. Многие считают, что Unicode и UTF-8 — одно и то же, но это не так. Есть и другие кодировки Unicode, но большая часть мира стандартизировалась на 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) — соответствующая кодовая точка Unicode.
Бинарные строки (строки байтов)
Бинарные строки или строки байтов состоят из байтов. Здесь нет символов, только байты. Все взаимодействие с внешним миром (любое за пределами текущего процесса Perl) происходит в бинарном формате.
Со строками байтов вы будете выполнять такие действия, как:
my (@length_content) = unpack "(V/a)*", $binary;
$binary =~ s/\x00\x0F/\xFF\xF0/; # for the brave :)
print {$fh} $binary;
my $byte_count = length $binary; Кодирование
Кодирование (как глагол) — это преобразование из текста в бинарный формат. Для кодирования вам необходимо указать целевую кодировку, например iso-8859-1 или UTF-8. Некоторые кодировки, такие как диапазон iso-8859 ("latin"), не поддерживают весь стандарт Unicode; символы, которые не могут быть представлены, теряются при преобразовании.
Декодирование
Декодирование — это преобразование из бинарного формата в текст. Для декодирования необходимо знать кодировку, использованную на стадии кодирования. И, прежде всего, это должна быть декодируемая кодировка. Не имеет смысла декодировать изображение PNG в строку текста.
Внутренний формат
Perl имеет внутренний формат, кодировку, используемую для кодирования текстовых строк для хранения в памяти. Все текстовые строки находятся в этом внутреннем формате. Фактически, текстовые строки никогда не находятся в другом формате!
Вам не нужно беспокоиться о том, что это за формат, потому что преобразование происходит автоматически при декодировании или кодировании.
Ваш новый инструментарий
Добавьте в стандартные заголовки следующую строку:
use Encode qw(encode decode); Или, если вы ленивы, просто:
use Encode; Поток ввода/вывода (собственно 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; И если используемый вами протокол поддерживает способ уведомления получателя о выбранной кодировке символов, пожалуйста, помогите получателю, используя эту возможность! Например, электронная почта и HTTP поддерживают заголовки MIME, поэтому вы можете использовать заголовок Content-Type. Они также могут иметь заголовок Content-Length, чтобы указать количество байтов, что всегда хорошая практика, если это число известно.
"Content-Type: text/plain; charset=UTF-8",
"Content-Length: $byte_count" РЕЗЮМЕ
Декодируйте всё, что получаете, кодируйте всё, что отправляете. (Если это текстовые данные.)
Вопросы и ответы (или часто задаваемые вопросы)
После прочтения этого документа, вам следует также прочитать perlunifaq, а затем perluniintro.
БЛАГОДАРНОСТИ
Спасибо Йохану Вромансу из Squirrel Consultancy. Его рассуждения об UTF-8 во время встреч Perl Mongers в Амстердаме заинтересовали меня и побудили узнать, как использовать кодировки символов в Perl так, чтобы они не ломались легко.
Спасибо Герарду Гуссену из TTY. Его презентация «UTF-8 в дикой природе» (Голландский Perl Workshop 2006) вдохновила меня опубликовать мои мысли и написать это руководство.
Спасибо людям, которые задавали вопросы об этом в различных каналах Perl IRC и постоянно напоминали мне о необходимости более простого объяснения.
Спасибо людям, которые просмотрели этот документ для меня, прежде чем он стал общедоступным. Это: Бенджамин Смит, Ян-Питер Корнет, Йохан Вроманс, Лукас Май, Нейтан Грей.
АВТОР
Юрд Ваальбоер <#####@juerd.nl>
СМОТРИТЕ ТАКЖЕ
perlunifaq, perlunicode, perluniintro, Encode
© 1993–2023 Larry Wall and others
Licensed under the GNU General Public License version 1 or later, or the Artistic License.
The Perl logo is a trademark of the Perl Foundation.
https://perldoc.perl.org/5.38.0/perlunitut