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 ("латинский"), не поддерживают весь стандарт 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" РЕЗЮМЕ
Декодируйте все, что вы получаете, закодируйте все, что отправляете (если это текстовые данные).
Вопросы и ответы (или FAQ)
После прочтения этого документа, вам следует также прочитать perlunifaq, а затем perluniintro.
БЛАГОДАРНОСТИ
Спасибо Йохану Вроману из Squirrel Consultancy. Его речи о UTF-8 во время встреч Perl Mongers в Амстердаме заинтересовали меня и побудили меня выяснить, как использовать кодировки символов в Perl способами, которые не легко ломаются.
Спасибо Герарду Гуссену из TTY. Его презентация «UTF-8 в дикой природе» (Голландский Perl Workshop 2006) вдохновила меня опубликовать свои мысли и написать этот учебник.
Спасибо людям, которые задавали вопросы об этом в различных каналах Perl IRC и постоянно напоминали мне, что нужен более простой способ объяснения.
Спасибо людям, которые проверили этот документ для меня, прежде чем он стал общедоступным. Это: Бенджамин Смит, Ян-Питер Корнет, Йохан Вроманс, Лукас Май, Нейтан Грей.
АВТОР
Юрд Валбоер <#####@juerd.nl>
СМОТРИТЕ ТАКЖЕ
perlunifaq, perlunicode, perluniintro, Encode
© 1993–2020 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.28.3/perlunitut