В Perl 5.8.x появилась более-менее нормальная поддержка формата UTF-8. Более того, все больше и больше «припирает» необходимость делать все проекты не в своей родной кодировке типа Windows-1251 (CP-1251), а в универсальной кодировке формата UTF-8.
Начиная исследование более «мягкого» переезда с родной кодировки (Windows-1251) на кодировку формата UTF-8 мы сталкиваемся с необходимостью делать следующее:
- Сохранять все скрипты и библиотеки в кодировке формата UTF-8;
- В начало каждого скрипта или библиотеки писать:
use utf8; - Следить за флагом UTF-8 каждой скалярной переменной с которой придется работать как с набором СИМВОЛОВ кодировки формата UTF-8;
- Использовать самые последние версии модулей для Perl; особое внимание следует уделить модулям интерфейсов и шаблонизаторов, например модуль CGI;
- Работать с базами данных преимущественно в кодировке формата UTF-8.
Теперь подробнее про каждый пункт.
1 и 2. Чтобы работать с символами UTF-8 как СИМВОЛАМИ сами СИМВОЛЫ можно представлять как \x-последовательности или же как сами символы. Работать с \x-последовательностями мягко сказать - не «наглядно». Возьмем простой пример:
print "\x{00ab}\x{d0b1}\x{d0bb}\x{d0b0}-\x{d0b1}\x{d0bb}\x{d0b0}-
\x{d0b1}\x{d0bb}\x{d0b0}\x{00bb}";
и:
print "«бла-бла-бла»";
Как видно, второй вариант намного понятнее.
Для того чтобы можно было в теле кода употреблять чистые символы, а не коды, и служит прагма utf8. Более того, эта прагма позволяет писать непосредственно в коде комментарии и некоторые литеральные лексемы.
3. UTF-8 это не просто формат, это еще и подход к доступу данных! Это стоит помнить каждый раз, когда по ходу написания кода будет встречаться строковая обработка с участием символов формата UTF-8. Дело в том, что некоторые символы UTF-8 обрабатываются не как символы UTF-8, а как символы ASCII! Например:
use utf8;my $string = "«";
print $string, "\n"; # На выходе: «
$string =~ s/«/-/; # На выходе: ᦏ-
и:
use utf8;
my $string = "«";
utf8::_utf8_on($string); # Принудительная установка флага UTF-8
print $string, "\n"; # На выходе: «
$string =~ s/«/-/; # На выходе: -
Функция _utf8_on() устанавливает флаг UTF-8. Эта функция является тестовой и приведена для наглядности. Более правильный способ - такой:
use utf8;
use Encode;
my $string = "«";
Encode::_utf8_on($string); # Принудительная установка флага UTF-8
print $string, "\n"; # На выходе: «
$string =~ s/«/-/; # На выходе: -
Или еще лучше:
use utf8;
use Encode;
my $string = "«";
Encode::decode_utf8($string); # Декодирование и установка флага UTF-8
print $string, "\n"; # На выходе: «
$string =~ s/«/-/; # На выходе: -
«Внутри» Perl каждый скаляр имеет «невидимый» флаг, состояние которого нужно контролировать каждый раз при установке и чтении значения этого скаляра. Для этого контроля существует группа функций пакета Encode:
_utf8_off, _utf8_on, is_utf8, utf8_downgrade, utf8_upgrade
В ближайшее время разработчики прагмы utf8 унаследуют эти функции. Первые попытки этого уже сделаны.
4. UTF-8 активно внедряется в Perl и его модули. Разработчики модулей активно начали изменять из реализацию руководствуясь новыми требованиями и стандартами. Для того, чтобы быть в ногу со временем нужно всегда контролировать те модули, которыми Вы будете пользоваться в своей работе и ярким представителем таковых является модуль CGI. Процедура param() модуля CGI 2.91 и младше не учитывали параметры в формате UTF-8, когда как новые учитывают, например:
if ($PARAM_UTF8) {
eval "require Encode; 1;" unless Encode->can('decode');
@result = map {ref $_ ? $_ : Encode::decode(utf8=>$_) } @result;
}
Таким образом совет: следите за свежестью модулей!
5. современные БД умеют работать с UTF-8, чтобы не «заморачиваться» с постоянными перекодировками, следует хранить, передавать и обрабатывать данные в БД в кодировке UTF-8! Если же стоит необходимость всё же конвертировать данные, то следует пользоваться функциями модуля Encode. В сети можно найти массу решений для конвертирования, но функции пакета Encode – самые надежные на сегодняшний день!
Метки: perl