Spec-Zone.ru › Perl 5.32

perlunitut

СОДЕРЖАНИЕ

  • НАЗВАНИЕ
  • ОПИСАНИЕ
    • Определения
      • Unicode
      • UTF-8
      • Строки текста (строки символов)
      • Бинарные строки (строки байтов)
      • Кодирование
      • Декодирование
      • Внутренний формат
    • Ваш новый набор инструментов
    • Поток ввода/вывода (собственно, обучающий курс на 5 минут)
  • РЕЗЮМЕ
  • Вопросы и ответы (или часто задаваемые вопросы)
  • БЛАГОДАРНОСТИ
  • АВТОР
  • СМОТРИТЕ ТАКЖЕ

НАЗВАНИЕ

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"

РЕЗЮМЕ

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

Вопросы и ответы (или часто задаваемые вопросы)

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

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

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

Спасибо Герарду Гуссену из TTY. Его презентация "UTF-8 в дикой природе" (Голландский Perl Workshop 2006) вдохновила меня опубликовать свои мысли и написать это руководство.

Спасибо людям, которые задавали вопросы об этом в различных каналах Perl IRC и постоянно напоминали мне, что нужна более простая формулировка.

Спасибо людям, которые просмотрели этот документ для меня перед его публикацией. Это: Benjamin Smith, Jan-Pieter Cornet, Johan Vromans, Lukas Mai, Nathan Gray.

АВТОР

Юрд Валбоер <#####@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.32.0/perlunitut

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API