Методы написания символов Юникода

Для написания символа Юникода в интерполируемых строках, для кодовых точек выше 0xFF используется обозначение \x{...} .

my $smiley = "\x{263a}";

Этот же метод используется и в литералах регулярных выражений.

$smiley =~ /\x{263a}/;

Для генерации Юникода во время исполнения также можете использовать chr():

my $hebrew_alef = chr(0x05d0);

См. "Дополнительные ресурсы" о том, какому числовому коду соответствует каждый символ Юникода.

Для обратного преобразования символа в кодировке Юникод в его числовой номер используется функция ord().

Обратите внимание, что \x..(без {} указываются только две шестнадцатеричные цифры), \x{...}, и chr(...) для аргументов меньше чем 0x100 (десятичное 256) порождают восьмибитный символ для обеспечения обратной совместимости со старыми версиями Perl. Для аргументов 0x100 или больше, всегда производятся символы Unicode. Если необходимо, чтобы всегда производились только Юникодовые символы независимо от их числового значения, используйте pack("U", ...) вместо \x.., \x{...}, или chr().

Подключив прагму charnames, вы можете в интерполируемых строках указывать символы Юникода по их наименованию:

use charnames ':full';
my $arabic_alef = "\N{ARABIC LETTER ALEF}";

И, как упоминалось выше, с помощью функции pack() можно получить символы Unicode по их номеру в кодовой таблице.

   my $georgian_an  = pack("U", 0x10a0);

Заметим, что внутри \x{...} и \N{...} не получится использовать переменные, так как они являются константами времени компиляции. Чтобы реализовать подобную функциональность во время исполнения, используйте chr() и charnames::vianame().

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

   my $chars = pack("U0W*", 0x80, 0x42);

С другой стороны, можно запретить интерпретацию аргументов как UTF-8 с помощью специального префикса "CO".

Обработка Юникода

Обработка Юникода в большинстве случаев очевидна: просто используйте строку как обычно. Функции подобные index(), length(), и substr(), регулярные выражения работают над символами Юникода. (см. perlunicode и perlretut).

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

use charnames ':full';
print length("\N{LATIN CAPITAL LETTER A}\N{COMBINING ACUTE ACCENT}"), "\n";

выведет 2, а не 1. Единственным исключением является то, что регулярное выражение использует \X для сопоставления расширенных кластеров графем.

Старые кодировки

Когда объединяется строка в старой кодировке со строкой Юникод, строку в старой кодировке нужно преобразовать в Юникод. Обычно предполагается ISO 8859-1 (или EBCDIC, если это возможно).

use Encode 'decode';
$data = decode("iso-8859-3", $data); # преобразование из старой кодировки в utf-8

Поддержка Юникода в Perl

Начиная с версии 5.6.0, в Perl была встроена поддержка Юникода. Однако Perl 5.8.0 - первый рекомендованный релиз для стабильной работы с Юникодом. В обслуживании релиза 5.6.1 зафиксированы множество проблем поддрежки Юникода, например регулярные выражения в данной версии не работают с Юникодом.

Начиная с Perl 5.8.0 использование use utf8 необходимо только в некоторых обстоятельствах. В более ранних версиях прагма utf8 использовалась для указания, что все операции в текущем блоке или файле должны быть Юникодовые(Unicode-aware). Эта модель оказалась неправильной или по крайней мере неуклюжей, в настоящее время поддержка Юникода осуществляется не в операциях в строковых данных. Остался только один случай, когда необходимо использовать use utf8: если ваш Perl скрипт сам закодирован в UTF-8, вы можете использовать UTF-8 в именах идентификаторов, в строках и в литералах регулярных выражений, если предварительно объявлен use utf8. Данная возможность по умолчанию не включена, поскольку в этом случае не поддерживается работа со старыми восьмибитными данными. См. utf8.

Модель Юникода в Perl

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

В настоящее время, Perl внутренне использует либо восьми-битную кодировку(например Latin-1), либо по умолчанию UTF-8 для кодирования Юникодовых строк. В частности, если все символы могут быть представлены кодами до 0xFF (в числовом представлении в пределах диапазона 0..255), Perl орудует байтами, в противном случае, использует UTF-8.

Пользователю Perl, как правило, не требуется знать и заботиться о том, как Perl внутренне производит кодирование строк, но это становится актуальным при выводе Юникодовых строк в поток минуя уровень PerlIO. Таким образом, родные байты используемые внутренне (родная кодировка символов или UTF-8, по мере необходимости для каждой строки) будут выводиться в неизменном виде, c выдачей предупреждения "Wide character", если эти строки содержат символы за пределами 0x00FF.

Например,

      perl -e 'print "\x{DF}\n", "\x{0100}\x{DF}\n"'

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

     Wide character in print at ...

Для вывода строк в UTF-8 следует указывать :encoding или :utf8 в выходной слой. Например

      binmode(STDOUT, ":utf8");

в этом примере программа гарантирует, что вывод будет в кодировке UTF-8, без выдачи предупреждений.

Вы можете включить автоматическую поддержку UTF-8 стандартного дескриптора файла, по умолчанию на уровне open(), и @ARGV с помощью ключа командной строки -C либо с помощью переменной окружающей среды PERL_UNICODE. Ключ -C подробнее рассматривается в perlrun.

Заметим, что это значит, что Perl будет ожидать такой же работы от других программ: если Perl полагает, что на STDIN поступают данные в формате UTF-8, он будет генерировать предупреждения если данные из внешнего источника не в UTF-8.

Все функции, в которых используется Юникод и операции ввода-вывода также требуют использования новой функциональности PerlIO. Почти все версии Perl начиная с 5.8 используют PerlIO, вы можете определить поддержку PerlIO для вашей версии Perl, командой perl -V, среди параметров о конфигурации Perl должна быть строка useperlio=define

perluniintro - Юникод в Perl: введение

Документ дает общее представление о кодировке Юникод(анг. Unicode) и о том, как Юникод используется в Perl.

Unicode

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

Юникод и ISO/IEC 10646 согласовали стандарты, которые представляют коды для символов большинства современных стандартов кодирования, охватывающих более чем 30 письменностей и сотни языков, включая все коммерчески-важные современные языки. Все символы крупнейших китайских, японских и корейских словарей так же кодируются. В конечном счете будут стандартизированы практически все символы в более чем 250 письменностей и тысяч языков. Юникод 1.0 был выпущен в октябре 1991, в настоящий момент последняя версия 5.2.

Символ Юникода - абстрактное понятие. Он не привязан к какой-либо постоянной величине числа. Юникод нейтрален к языку и его отображению: он не кодирует язык текста, не определяет шрифты и другие детали графического отображения. Юникод оперирует над символами и над построением текста из этих символов.

Юникод определяет символы, такие как LATIN CAPITAL LETTER A или GREEK SMALL LETTER ALPHA и их уникальные числа, например вышеприведенным символам соответствуют их числовые представления 0x0041 и 0x03b1. Эти уникальные числа назваются - коды символов.

Стандарт Юникода предпочитает использование шестнадцатеричного представления кодов. Если такие номера как 0x0041 вам не знакомы, загляните в раздел, Шестнадцатеричное представление. В стандарте Юникода используется обозначение такое как U+0041 LATIN CAPITAL LETTER A, чтобы указать шестнадцатеричный код и нормативное имя символа.

Юникод также определяет различные свойства для символов, такие как "прописной" или "строчный", "десятичное число", или "знак препинания". Эти свойства независимы от имен символов. Кроме того, определены различные операции над символами такие как "Возведение в верхний регистр" или "Возведение в нижний регистр", и упорядочивание(сортировка) (анг. collating).

Логический "символ" Юникода может на самом деле состоять из более чем одного внутренннего фактического "символа" или кода. Для западных языков символы Юникода корректно моделируются на основе базовых символов (например, LATIN CAPITAL LETTER A) c дополнительными модификаторами (например, COMBINING ACUTE ACCENT). Такая последовательность базовых символов и модификаторов называется последовательностью комбинированных символов(combining character sequence). Некоторые не западные языки требуют более сложных моделей, поэтому Юникод создал концепцию - кластеры графем (анг. grapheme cluster) и затем рассширенные кластеры графем. К примеру, слог корейской письменности Хангыль считается одним логическим символом, но чаще всего состоит из трех символов Юникода: после ведущего согласного следует внутренний гласный после которого в свою очередь следует конечный согласный.

Будем называть эти расширенные кластеры графем "символами", относительно их внешнего представления. Как программист, вы будете стремиться оперировать отдельными элементами (или символами) кластера, хотя с точки зрения пользователя кластер графем будет восприниматься как один символ.

В этом документе мы будем подразумевать под словом "символ" - символ Юникода.

Для некоторых сочетаний есть их монолитные (precomposed) варианты. Например, LATIN CAPITAL LETTER A WITH ACUTE определяется как один код. Однако, монолитные варианты символов имеются только для некоторых сочетаний, и в основном предназначены для поддержки прямой и обратной совместимости между Юникодом и традиционными стандартами(например, ISO 8859). В общем случае, составной метод (composing method) более расширяем. Для поддержки преобразования между различными составными символами определены формы нормализации для приведения текста к определенному стандарту.

Юникод определяет несколько форм кодировок символов (character encoding forms), из которых UTF-8 наиболее популярна. UTF-8 - кодировка переменной ширины, в которой символы кодируются от 1 до 6 байтов. Кроме UTF-8 развиваются стандарты кодировок UTF-16 и UTF-32. ISO/IEC 10646 определяет аналогичные формы кодирования UCS-2 (аналогичен UTF-16) и UCS-4 (аналогичен UTF-32).

Подробнее о кодировках см. в документе perlunicode.

Продолжение следует ...

Ниже представлен вольный перевод параграфа из страницы документа perlmod - BEGIN, UNITCHECK, CHECK, INIT and END

Пять специально именованных блоков кода выполняются во время запуска и завершения программы Perl, Этими блоками являются BEGIN , UNITCHECK , CHECK , INIT , и END .

Блоки могут быть объявлены c префиксом sub чтобы создать видимость подпрограммы (хотя это не считается хорошим стилем). Следует отметить, что они на самом деле не существуют как именованные подпрограммы (несмотря на их внешний вид). Вы можете объявлять несколько таких блоков в программе и каждый из них будет выполнен в подходящий для каждого из них момент. Поэтому вы не можете вызвать любой из этих блоков кода, как обычную подпрограмму.

Блок BEGIN выполняется как можно раньше, то есть, сразу после того как он полностью определен, даже перед остальным содержимым файла (или строки), который был проанализирован. Вы можете использовать несколько BEGIN блоков в файле (или в eval'ed строки ) - они будут выполняться в порядке определения.

Вследствие того, что блог BEGIN выполняется немедленно, он может тянуть за собой определения подпрограмм, а так же из других файлов во время видимых в остальной скомпилированной и выполненной части. После того, как BEGIN сработан, он сразу становится неопределенным и любой код, который он использовал возвращается в пул памяти Perl.

     --EN--
    Because a C<BEGIN> code block executes immediately, it
    can pull in definitions of subroutines and such from
    other files in time to be visible to the rest of the
    compile and run time.  Once a C<BEGIN> has run, it is
    immediately undefined and any code it used is returned
    to Perl's memory pool. 

Следует отметить, что блоки BEGIN и UNITCHECK срабатывают внутри строк, скомпилированных в eval(). Блоки кода CHECK и INIT не выполняются внутри строк eval, что может привести к проблемам в среде mod_perl.

Блок кода END выполняется как можно позже, т.е после того, как perl завершил выполнение программы и непосредственно перед выходом интерпретатора, даже если программа завершается в результате вызова функции die(). (Но только, если это не морфинг в другую программу через exec, или программа не завершена по системному сигналу). Вы можете определять несколько блоков END в файле, они будут выполняться в обратном порядке их определения, а именно по принципу: последним пришел, первым вышел (LIFO). Блоки END не выполняются когда при запуске программы вы указываете ключ -c или если компиляция программы не удалась.

Обратите внимание, что блок кода END НЕ выполняется после завершения выполнения кода в eval(): если любой END блок создан в строке eval(), он будет выполнен так же как и любые другие END блоки этого пакета в порядке LIFO перед выходом интерпретатора.

Внутри блока END переменная $? содержит статус, означающий, что программа собирается вызвать exit(). Вы можете менять $? это значение выхода из программы. Остерегайтесь случайного изменения $? (например, в результате выполения другой программы через system()).

Блоки кода UNITCHECK , CHECK и INIT полезны, когда нужно что либо сделать между этапом компиляции и этапом исполнения основной программы.

Блоки UNITCHECK выполняются сразу после секции которая после их определения была скомпилирована. Основная часть программы и каждый загруженый модуль части компилации, как строка в eval, код, скомпилированный в конструкции (?{ }) в регулярных выражениях, вызовы в do FILE , require FILE , и код после ключа -e в командной строке.

     --EN--
    C<UNITCHECK> blocks are run just after the unit which
    defined them has been compiled.  The main program file
    and each module it loads are compilation units, as are
    string C<eval>s, code compiled using the C<(?{ })>
    construct in a regex, calls to C<do FILE>, C<require
    FILE>, and code after the C<-e> switch on the command
    line. 

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

Блоки INIT запускаются непосредственно перед тем как Perl начнет выполнять программу, в порядке "первым пришел, первым вышел" (FIFO).

Блоки CHECK и INIT не будут выполняться внутри строки eval(), если это происходит после окончания основной фазы компиляции; что может быть проблемой в mod_perl и в другой постоянной среде, которая использует eval STRING для загрузки кода во время исполнения.

При использовании ключей командной строки -n и -p, блоки BEGIN и END работают как в awk. Блоки BEGIN и CHECK также выполняются когда программа запускается с ключом -c для проверки синтаксиса, хотя основной код не выполняется.

   #!/usr/bin/perl
  
  # begincheck
  
  print         "10. Обычный код выполняется во время исполнения программы.\n";
  
  END { print   "16.   Так это и есть конец истории.\n" }
  INIT { print  " 7. Блоки INIT выполняются непосредственно перед выполнением основной части программы.\n" }
  UNITCHECK {
    print       " 4.   И поэтому перед любыми блоками CHECK.\n"
  }
  CHECK { print " 6.   Так, это в шестой строке.\n" }
  
  print         "11.   Это, разумеется выполняется в общей очереди.\n";
  
  BEGIN { print " 1. Блоки BEGIN выполняются во время компиляции в порядке FIFO.\n" }
  END { print   "15.   Читайте perlmod чтобы узнать всю историю.\n" }
  CHECK { print " 5. Блоки CHECK выполняются в порядке LIFO после компиляции всей программы.\n" }
  INIT { print  " 8.   Выполняет это также при использовании ключа -c.\n" }
  
  print         "12.   Это анти-темный(anti-obfuscated) код.\n";
  
  END { print   "14. Блоки END выполняются в порядке LIFO после завершения основной программы.\n" }
  BEGIN { print " 2.   Так это строка выходит второй.\n" }
  UNITCHECK {
   print " 3. Блоки UNITCHECK выполняются в порядке LIFO после завершения компиляции файла.\n"
  }
  INIT { print  " 9.   Вы увидите разницу сразу.\n" }
  
  print         "13.   Хотя визуально строка последняя, это не должно вводить вас в заблуждение.\n";
 

Statistic