Это неинтересное, это про программирование.
Допустим, Вы - программист, пишущий на Perl. И вот приспичило Вам использовать в своих программах UTF-8.
Прочитали про внутреннее представление строк в Perl, про флажки-костыли, про управление ими... Начали с переменных:
use strict;
use warnings;
my $a = 'дададад!';
print($a, ' ', length($a));
^D
дададад! 15
Хм.. длина определилась неверно. Но мы-то знаем нужную прагму! Добавляем 'use utf8':
use strict;
use warnings;
use utf8;
my $a = 'дададад!';
print($a, ' ', length($a));
^D
Wide character in print at - line 5.
дададад! 8
Длина теперь верная, но появились странные предупреждения... А, надо этому Perl объяснить, что STDOUT (да и остальные STD*) - они готовы работать с UTF-8, объявим это через очередную "волшебную" прагму 'use open':
use strict;
use warnings;
use utf8;
use open qw{:std :utf8};
my $a = 'дададад!';
print($a, ' ', length($a));
^D
дададад! 8
На первый взгляд, всё красиво и правильно. Но мы ж настоящие программисты, мы ж такими hello-world'ами не ограничиваемся. Давайте что-нибудь "выдернем" из СУБД через DBI. Что-нибудь UTF'ное. =) Допустим, из MySQL. Допустим, табличка там имеет DEFAULT CHARSET=utf8. Допустим, удачно подключились, получили рабочий handler ($dbh), как вариант, сказали туда "SET NAMES utf8". Вытаскиваем:
my $sql = 'select key_id, name from key_pack where key_id = 1';
my @rc = $dbh->selectrow_array($sql);
print($rc[1], ' ', length($rc[1]), "\n");
^D
пакеÑик 14
Таааак.. Программа у нас UTF'ная, а DBI гонит какой-то raw-поток байтов. Придётся его подровнять. Напишем wrapper:
sub dbi_utf8_on_array
{
map {utf8::decode($_) unless utf8::is_utf8($_)} @_;
return @_;
}
my $sql = 'select key_id, name from key_pack where key_id = 1';
my @rc = dbi_utf8_on_array($dbh->selectrow_array($sql));
print($rc[1], ' ', length($rc[1]), "\n");
^D
пакетик 7
Вот, теперь порядок. Но мы ж можем использовать не только selectrow_array(), но и другие DBI-функции. Придётся и для них wrapper'ы писать, типа:
sub dbi_utf8_on_arrayref
{
my $ref = shift;
map {utf8::decode($_) unless utf8::is_utf8($_)} @{$ref};
return $ref;
}
Теперь положим, что мы пишем для web и нам надо вывести HTML-документ. Мы в ВУЗе учились, там нам рассказывали, что отделять логику приложения от оформления результата - это хорошо. Поэтому мы до сих пор используем механизмы шаблонов. Возьмём что-нибудь простенькое, HTML::Template, подключим:
my $tmpl = HTML::Template->new(filename => 'example.html',
die_on_bad_params => 0,
loop_context_vars => 1) || die('Can not create HTML::Template obj');
print($tmpl->output());
..и получим в выводе что-то типа:
Ах, вот как! Оказывается, файл шаблона открывается не как :utf8, а как какой-то :bytes! Можно, конечно, пакет "врукопашную" поправить, но это не наш метод! Можно предварительно открыть файл с шаблоном как :utf8 и передать конструктору file hander, можно потом "перекодировать" результат, непосредственно перед выводом:
my $out = $tmpl->output();
utf8::decode($out);
print($out);
Тогда получим что-то более осмысленное:
Теперь представим, что программа усложнилась и нам её надо отладить. До отладчика тянуться далеко, нам бы просто наглядно посмотреть содержимое переменной. Для этого можно использовать пакет Data::Dumper:
use Data::Dumper;
my $a = 'дададад';
print(Dumper($a), "\n");
^D
$VAR1 = "\x{434}\x{430}\x{434}\x{430}\x{434}\x{430}\x{434}";
Замечательно! Всё правильно, только нечитабельно. Сейчас подхачим этот Dumper:
use Data::Dumper;
$Data::Dumper::Useqq = 1;
{
no warnings 'redefine';
sub Data::Dumper::qquote
{
my $s = shift;
return "'$s'";
}
}
my $a = 'дададад';
print(Dumper($a), "\n");
^D
$VAR1 = 'дададад';
Уфф.. Вот и ладушки!..
...и так с каждым очередным используемым "механизмом" - или приколачиваем туда свои костыли, или ищем ручки управления заранее встроенными туда костылями. Можно "откинуться на спинку кресла" и посмотреть на полученный код - это ж сороконожка и вся на костылях!
Вы всё ещё хотите использовать Perl? =)