кодировка
СОДЕРЖАНИЕ
- НАЗВАНИЕ
- ПРЕДУПРЕЖДЕНИЕ
- СИНОПСИС
- ОПИСАНИЕ
- НАСТРОЙКИ
- ЗАМЕЧАНИЯ
- ПРИМЕР - Greekperl
- ОШИБКИ
- ИСТОРИЯ
- СМОТРИТЕ ТАКЖЕ
НАЗВАНИЕ
encoding — позволяет писать скрипты в кодировках, отличных от ASCII и UTF-8
ПРЕДУПРЕЖДЕНИЕ
Этот модуль устарел с версии Perl v5.18. См. "ОПИСАНИЕ" и "ОШИБКИ".
СИНОПСИС
use encoding "greek"; # Perl like Greek to you?
use encoding "euc-jp"; # Jperl!
# or you can even do this if your shell supports your native encoding
perl -Mencoding=latin2 -e'...' # Feeling centrally European?
perl -Mencoding=euc-kr -e'...' # Or Korean?
# more control
# A simple euc-cn => utf-8 converter
use encoding "euc-cn", STDOUT => "utf8"; while(<>){print};
# "no encoding;" supported
no encoding;
# an alternate way, Filter
use encoding "euc-jp", Filter=>1;
# now you can use kanji identifiers -- in euc-jp!
# encode based on the current locale - specialized purposes only;
# fraught with danger!!
use encoding ':locale'; ОПИСАНИЕ
Этот псевдоним используется для того, чтобы Perl-скрипт мог быть написан в кодировках, которые не являются строго ASCII или UTF-8. Он преобразует все или части скрипта Perl из заданной кодировки в UTF-8 и изменяет слои PerlIO для STDIN и STDOUT на указанную кодировку.
Этот псевдоним относится к временам, когда UTF-8-совместимые редакторы были редкостью. Но это было давно, и необходимость в нём сильно уменьшилась. Это, вместе с тем фактом, что он не работает с потоками, а также с другими проблемами (см. "ОШИБКИ"), привели к его устареванию. Планируется удалить этот псевдоним в будущей версии Perl. Новый код следует писать в UTF-8 и использовать псевдоним use utf8 вместо него (см. perluniintro и utf8 для получения подробностей). Старый код следует преобразовать в UTF-8, используя что-то вроде рецепта в "СИНОПСИСЕ" (хотя этот простой подход может потребовать последующих ручных корректировок).
Если UTF-8 не подходит, рекомендуется использовать простой фильтр кодировки, например, тот, который предоставляется модулем Filter::Encoding в CPAN, или собственным параметром Filter этого псевдонима (см. ниже).
Единственное законное использование этого псевдонима — почти наверняка только одно на файл, в начале, со сферой действия файла, так как файл, скорее всего, будет написан только в одной кодировке. В Perls до v5.22 применяются дополнительные ограничения (см. "До Perl v5.22").
Существует два основных режима работы (плюс отключение):
-
use encoding ['ENCNAME'] ; -
Примечание: Этот режим работы больше не поддерживается начиная с Perl v5.26.
Это обычный режим работы. Он преобразует различные литералы, встречающиеся в исходном файле Perl, из кодировки ENCNAME в UTF-8 и аналогично преобразует числовые коды символов. Это используется, когда скрипт является комбинацией ASCII (для имён переменных и знаков препинания и т.д.), но данные литералов находятся в указанной кодировке.
ENCNAME является необязательным. Если он опущен, используется кодировка, указанная в переменной окружения
PERL_ENCODING. Если она не установлена или разрешённая кодировка не известнаEncode, будет выброшено сообщение об ошибкеUnknown encoding 'ENCNAME'.Начиная с Perl v5.8.6 (
Encodeверсия 2.0.1), ENCNAME может быть именем:locale. Это для очень специализированных приложений и документировано в "Под-псевдониме :locale" ниже.Литералы, которые преобразуются, — это
q//, qq//, qr//, qw///, qx//, а начиная с v5.8.1, —tr///. Операции, которые выполняют преобразования, включаютchr,ord,utf8::upgrade(но неutf8::downgrade) иchomp.Также начиная с v5.8.1, псевдо-файловый дескриптор
DATAпреобразуется из кодировки в UTF-8.Например, вы можете написать код на EUC-JP следующим образом:
my $Rakuda = "\xF1\xD1\xF1\xCC"; # Camel in Kanji #<-char-><-char-> # 4 octets s/\bCamel\b/$Rakuda/;И с
use encoding "euc-jp"в эффекте, это то же самое, что и этот код в UTF-8:my $Rakuda = "\x{99F1}\x{99DD}"; # two Unicode Characters s/\bCamel\b/$Rakuda/;См. "ПРИМЕР" ниже для более полного примера.
Если
${^UNICODE}(доступно начиная с v5.8.2) существует и отлично от нуля, слои PerlIOSTDINиSTDOUTбудут установлены в ":encoding(ENCNAME)". Поэтомуuse encoding "euc-jp"; my $message = "Camel is the symbol of perl.\n"; my $Rakuda = "\xF1\xD1\xF1\xCC"; # Camel in Kanji $message =~ s/\bCamel\b/$Rakuda/; print $message;выведет
"\xF1\xD1\xF1\xCC is the symbol of perl.\n"а не
"\x{99F1}\x{99DD} is the symbol of perl.\n"Вы можете переопределить это, указав дополнительные аргументы; см. ниже.
Обратите внимание, что
STDERRНЕ будет изменено независимо от этого.Также обратите внимание, что нестандартные файловые дескрипторы останутся без изменений. Используйте
use openилиbinmodeдля изменения слоёв этих дескрипторов. -
use encoding ENCNAME, Filter=>1; -
Он работает так же, как выше, но аргумент
Filterсо значением, отличным от нуля, заставляет весь скрипт, а не только литералы, быть преобразованным из кодировки в UTF-8. Это позволяет идентификаторам в исходном коде также быть в этой кодировке. (Проблемы могут возникнуть, если кодировка не является надмножеством ASCII; представьте себе, что все ваши точки с запятой переводятся в что-то другое.) Вы можете использовать этот вариант, чтобы заставить${"\x{4eba}"}++работать. (Это эквивалентно
$human++, где human — один иероглиф.)Это фактически означает, что ваш исходный код ведёт себя так, как будто он был написан в UTF-8 с
'use utf8в силе. Так что даже если ваш редактор поддерживает только Shift_JIS, например, вы всё равно можете попробовать примеры из главы 15Programming Perl, 3rd Ed..Этот вариант значительно медленнее, чем другой.
-
no encoding; -
Сбрасывает кодировку скрипта. Слои
STDIN,STDOUTсбрасываются до ":raw" (по умолчанию — необработанный поток байтов).
НАСТРОЙКИ
Установка STDIN и/или STDOUT индивидуально
Кодировки STDIN и STDOUT могут быть установлены индивидуально параметрами псевдонима:
use encoding 'euc-tw', STDIN => 'greek' ...; В этом случае вы не можете опустить первый ENCNAME. STDIN => undef полностью отключает преобразование ввода-вывода для данного файлового дескриптора.
Когда ${^UNICODE} (доступно начиная с v5.8.2) существует и отлично от нуля, эти параметры будут полностью проигнорированы. См. "${^UNICODE}" в perlvar и "-C" в perlrun для подробностей.
Под-псевдоним :locale
Начиная с v5.8.6, имя кодировки может быть :locale. Это означает, что кодировка берётся из текущего региональных настроек, а не жёстко задаётся псевдонимом. Поскольку скрипт действительно может быть закодирован только в одной кодировке, этот параметр опасен. Он имеет смысл только в том случае, если сам скрипт написан на ASCII, и все возможные региональные настройки, которые будут использоваться при выполнении скрипта, являются надмножествами ASCII. Это означает, что сам скрипт не изменяется, но файловые дескрипторы получают указанную кодировку, а операции, такие как chr и ord, используют эту кодировку.
Логика определения региональных настроек :locale, которые использует:
-
Если платформа поддерживает интерфейс
langinfo(CODESET), используется кодировка, возвращённая как значение по умолчанию для псевдонима open. -
Если 1. не сработало, но мы находимся в псевдониме locale, переменные среды
LC_ALLиLANG(в указанном порядке) сравниваются с кодировками (часть после ".", если таковая имеется), и если найдено совпадение, это используется в качестве кодировки по умолчанию для псевдонима open. -
Если 1. и 2. не сработали, переменные среды
LC_ALLиLANG(в указанном порядке) сравниваются на предмет чего-либо, похожего на UTF-8, и если найдено совпадение,:utf8используется в качестве кодировки по умолчанию для псевдонима open.
Если ваши переменные среды региональных настроек (LC_ALL, LC_CTYPE, LANG) содержат строки 'UTF-8' или 'UTF8' (регистронезависимое сравнение), кодировка по умолчанию для вашего STDIN, STDOUT, и STDERR, и любого последующего открытия файла, будет UTF-8.
ЗАМЕЧАНИЯ
ПОБОЧНЫЕ ЭФФЕКТЫ
-
Если псевдоним
encodingнаходится в области видимости, то возвращаемые длины вычисляются из длины$/в символах Юникода, что не всегда совпадает с длиной$/в родной кодировке. -
Без этого псевдонима, если строки, работающие с байтами, и строки с данными символов Юникода конкатенируются, новая строка будет создана путём декодирования строк байтов как ISO 8859-1 (Latin-1).
Псевдоним encoding изменяет это, используя указанную кодировку вместо неё. Например:
use encoding 'utf8'; my $string = chr(20000); # a Unicode string utf8::encode($string); # now it's a UTF-8 encoded byte string # concatenate with another Unicode string print length($string . chr(20000));Выведет
2, потому что$stringулучшается до UTF-8. Безuse encoding 'utf8';, он выведет4вместо этого, так как$stringсостоит из трёх октетов при интерпретации как Latin-1.
НЕ СМЕШИВАЙТЕ НЕСКОЛЬКО КОДИРОВОК
Обратите внимание, что только литералы (строки или регулярные выражения), содержащие только устаревшие кодовые точки, подвергаются воздействию: если вы смешиваете данные такого типа
\x{100}\xDF
\xDF\x{100} данные предполагаются в (Latin 1 и) Юникоде, а не в вашей родной кодировке. Другими словами, это будет соответствовать в "греческом":
"\xDF" =~ /\x{3af}/ но это не будет
"\xDF\x{100}" =~ /\x{3af}\x{100}/ поскольку \xDF (ISO 8859-7 GREEK SMALL LETTER IOTA WITH TONOS) слева не будет обновлено до \x{3af} (Unicode GREEK SMALL LETTER IOTA WITH TONOS) из-за \x{100} слева. Вам не следует смешивать устаревшие данные и Юникод в одной строке.
Этот пragma также влияет на кодировку диапазона кодовых точек 0x80..0xFF: обычно символы в этом диапазоне остаются байтами по 8 бит (если они не сочетаются с символами с кодовыми точками 0x100 или больше, в этом случае все символы должны быть закодированы в UTF-8), но если пragma encoding присутствует, то даже диапазон 0x80..0xFF всегда кодируется в UTF-8.
В конце концов, самое лучшее в этом pragma то, что вам не нужно прибегать к \x{....}, чтобы просто написать своё имя в родной кодировке. Поэтому не стесняйтесь помещать свои строки в кодировке в кавычки и в выражениях regex.
До Perl v5.22
Pragma был лексическим по всему скрипту, а не по блокам. Только последний use encoding или no encoding имел значение, и он влиял на весь скрипт. Однако, пragma no encoding поддерживался и use encoding мог появляться в данном скрипте любое количество раз (хотя эффективным был только последний).
Поскольку область действия не была лексической, использование chr, ord, и т.д. другими модулями, тоже влияло. Это приводило к странным и неверным действиям на расстоянии, которые трудно отлаживать.
Это означает, что вам нужно быть очень внимательным к порядку загрузки:
# called module
package Module_IN_BAR;
use encoding "bar";
# stuff in "bar" encoding here
1;
# caller script
use encoding "foo"
use Module_IN_BAR;
# surprise! use encoding "bar" is in effect. Лучший способ избежать этой странности — использовать этот pragma СРАЗУ после загрузки других модулей. Т.е.
use Module_IN_BAR;
use encoding "foo"; До версии Encode 1.87
-
STDINиSTDOUTне устанавливались в опции фильтра. АSTDIN=>ENCODINGиSTDOUT=>ENCODINGработали не так, как в версии без фильтра. -
use utf8не объявлялся неявно, поэтому вам нужноuse utf8для выполнения${"\x{4eba}"}++
До Perl v5.8.1
- "NON-EUC" кодировки с двойным байтом
-
Так как Perl нужно проанализировать скрипт до применения этого pragma, такие кодировки, как Shift_JIS и Big-5, которые могут содержать
'\'(обратный слэш;\x5c) во втором байте, терпят неудачу, потому что второй байт может случайно экранировать следующий символ кавычки. -
tr/// -
Pragma encoding работает, декодируя литералы строк в
q//,qq//,qr//,qw///, qx//и так далее. В Perl v5.8.0 это не относится кtr///. Поэтому,use encoding 'euc-jp'; #.... $kana =~ tr/\xA4\xA1-\xA4\xF3/\xA5\xA1-\xA5\xF3/; # -------- -------- -------- --------Не работает как
$kana =~ tr/\x{3041}-\x{3093}/\x{30a1}-\x{30f3}/;- Легенда символов выше
-
utf8 euc-jp charnames::viacode() ----------------------------------------- \x{3041} \xA4\xA1 HIRAGANA LETTER SMALL A \x{3093} \xA4\xF3 HIRAGANA LETTER N \x{30a1} \xA5\xA1 KATAKANA LETTER SMALL A \x{30f3} \xA5\xF3 KATAKANA LETTER N
Это нелогичное поведение исправлено в Perl v5.8.1.
В Perl v5.8.0 вы можете обойти это следующим образом;
use encoding 'euc-jp'; # .... eval qq{ \$kana =~ tr/\xA4\xA1-\xA4\xF3/\xA5\xA1-\xA5\xF3/ };Обратите внимание, что выражение
tr//заключено вqq{}. Идея в том же, что и в классическом приёме, который позволяетtr///'интерполировать':tr/$from/$to/; # wrong! eval qq{ tr/$from/$to/ }; # workaround.
ПРИМЕР - Greekperl
use encoding "iso 8859-7";
# \xDF in ISO 8859-7 (Greek) is \x{3af} in Unicode.
$a = "\xDF";
$b = "\x{100}";
printf "%#x\n", ord($a); # will print 0x3af, not 0xdf
$c = $a . $b;
# $c will be "\x{3af}\x{100}", not "\x{df}\x{100}".
# chr() is affected, and ...
print "mega\n" if ord(chr(0xdf)) == 0x3af;
# ... ord() is affected by the encoding pragma ...
print "tera\n" if ord(pack("C", 0xdf)) == 0x3af;
# ... as are eq and cmp ...
print "peta\n" if "\x{3af}" eq pack("C", 0xdf);
print "exa\n" if "\x{3af}" cmp pack("C", 0xdf) == 0;
# ... but pack/unpack C are not affected, in case you still
# want to go back to your native encoding
print "zetta\n" if unpack("C", (pack("C", 0xdf))) == 0xdf; ОШИБКИ
- Безопасность потоков
-
use encoding ...не является потокобезопасным (т.е. не используйте в потоковых приложениях). - Нельзя использовать более чем в одном модуле в одной программе.
-
Разрешена только одна кодировка. Если вы объединяете модули в программе, которые имеют разные кодировки, будет использоваться только одна.
-
Другие модули, использующие
STDINиSTDOUTполучают закодированный поток -
Они могут ожидать совершенно другого.
- Литералы в regex, превышающие 127 байт
-
Для собственных многобайтовых кодировок (фиксированной или переменной длины) текущая реализация регулярных выражений может вызвать ошибки перекодировки для литералов регулярных выражений, превышающих 127 байт.
- EBCDIC
-
Pragma encoding не поддерживается на платформах EBCDIC.
format-
Этот pragma не очень хорошо работает с
format, потому что PerlIO плохо с ним сочетается. Когдаformatсодержит не-ASCII символы, он печатает странные символы или генерирует "предупреждения о символах с большой шириной". Чтобы понять это, попробуйте код ниже.# Save this one in utf8 # replace *non-ascii* with a non-ascii string my $camel; format STDOUT = *non-ascii*@>>>>>>> $camel . $camel = "*non-ascii*"; binmode(STDOUT=>':encoding(utf8)'); # bang! write; # funny print $camel, "\n"; # fineБез binmode это работает, но без binmode print() терпит неудачу вместо write().
В любом случае, само использование
formatсомнительно в отношении символов Unicode, так как нужно учитывать такие вещи, как ширина символов (например, двойная ширина для иероглифов) и направления (например, BIDI для арабского и иврита). - См. также "ОСОБЕННОСТИ"
ИСТОРИЯ
Этот pragma впервые появился в Perl v5.8.0. Он был улучшен в последующих версиях, как указано выше.
См. также
perlunicode, Encode, open, Filter::Util::Call,
Гл. 15 в Programming Perl (3rd Edition) Ларри Уолла, Тома Кристиансена, Джона Орванта; O'Reilly & Associates; ISBN 0-596-00027-8
© 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.30.3/encoding