кодировка
СОДЕРЖАНИЕ
- НАЗВАНИЕ
- ПРЕДУПРЕЖДЕНИЕ
- СИНОПСИС
- ОПИСАНИЕ
- ПАРАМЕТРЫ
- ЗАМЕЧАНИЯ
- ПРИМЕР - 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'; ОПИСАНИЕ
Этот pragma используется для того, чтобы Perl-скрипт мог быть написан в кодировках, которые не являются строго ASCII или UTF-8. Он переводит весь или части скрипта Perl-программы из заданной кодировки в UTF-8 и изменяет слои PerlIO STDIN и STDOUT на указанную кодировку.
Этот pragma относится к временам, когда UTF-8-совместимые редакторы были редкостью. Но это было давно, и необходимость в нём значительно уменьшилась. Это, наряду с тем, что он не работает с потоками, а также с другими проблемами (см. "ОШИБКИ"), привело к его устареванию. Планируется удалить этот pragma в будущей версии Perl. Новый код должен быть написан в UTF-8, и должен использоваться pragma use utf8 вместо него (см. perluniintro и utf8 для подробностей). Старый код следует преобразовать в UTF-8, например, по рецепту в "СИНОПСИСЕ" (хотя этот простой подход может потребовать последующей ручной корректировки).
Если UTF-8 не подходит, рекомендуется использовать простой фильтр кодировки, например, предоставленный модулем Filter::Encoding на CPAN, или опцией Filter данного pragmy (см. ниже).
Единственным законным использованием этого pragmy, почти наверняка, является одно использование на файл, в начале файла, так как файл, скорее всего, будет написан только в одной кодировке. Дополнительные ограничения действуют в Perl'ях до версии 5.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. Это предназначено для очень специализированных применений и документировано в "Под-pragma:locale" ниже.Литералы, которые преобразуются, это
q//, qq//, qr//, qw///, qx//, и начиная с версии 5.8.1,tr///. К операциям, которые выполняют преобразования, относятсяchr,ord,utf8::upgrade(но неutf8::downgrade), иchomp.Также начиная с версии 5.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 можно индивидуально задать параметрами pragmy:
use encoding 'euc-tw', STDIN => 'greek' ...; В этом случае вы не можете опустить первый ENCNAME. STDIN => undef полностью отключает транскодирование ввода-вывода для этого файлового дескриптора.
Когда ${^UNICODE} (доступно начиная с v5.8.2) существует и не равно нулю, эти параметры будут полностью проигнорированы. См. "${^UNICODE}" в perlvar и "-C" в perlrun для подробностей.
Под-pragma :locale
Начиная с версии 5.8.6, имя кодировки может быть :locale. Это означает, что кодировка берётся из текущего локали, а не жёстко задаётся pragma. Поскольку скрипт действительно может быть закодирован только в одной кодировке, этот вариант опасен. Он имеет смысл только в том случае, если сам скрипт написан на ASCII, а все возможные локали, которые будут использоваться при выполнении скрипта, являются надмножествами ASCII. Это означает, что сам скрипт не меняется, но файловые дескрипторы получают указанную кодировку, и операции, такие как chr и ord, используют эту кодировку.
Логика определения локали, используемой :locale, такова:
-
Если платформа поддерживает интерфейс
langinfo(CODESET), используемый кодовый набор используется в качестве кодировки по умолчанию для pragmy open. -
Если 1. не сработало, но мы находимся под pragma locale, переменные окружения
LC_ALLиLANG(в указанном порядке) проверяются на соответствие кодировкам (часть после ".", если есть), и если найдена, она используется как кодировка по умолчанию для pragmy open. -
Если 1. и 2. не сработали, переменные окружения
LC_ALLиLANG(в указанном порядке) проверяются на соответствие чему-либо, похожему на UTF-8, и если найдено, то:utf8используется как кодировка по умолчанию для pragmy open.
Если ваши переменные окружения локали (LC_ALL, LC_CTYPE, LANG) содержат строки 'UTF-8' или 'UTF8' (регистронезависимое соответствие), кодировка по умолчанию ваших STDIN, STDOUT, STDERR, а также любого последующего открытия файла, будет UTF-8.
ЗАМЕЧАНИЯ
ПОБОЧНЫЕ ЭФФЕКТЫ
-
Если pragma
encodingнаходится в области действия, то длины вычисляются по длине$/в символах Юникода, что не всегда совпадает с длиной$/в родной кодировке. -
Без этого pragmy, если строки, работающие с байтовыми семантикой и строки с данными Юникода, конкатенируются, новая строка создаётся путём декодирования байтовых строк как ISO 8859-1 (Latin-1).
Pragma 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} слева. Не следует смешивать устаревшие данные и Юникод в одной строке.
Этот pragma также влияет на кодировку диапазона кодов 0x80..0xFF: обычно символы в этом диапазоне остаются восьмибитными байтами (если они не комбинируются с символами с кодами 0x100 или больше, в этом случае все символы должны быть закодированы в UTF-8), но если pragma encoding присутствует, даже диапазон 0x80..0xFF всегда кодируется в UTF-8.
В конечном счете, лучшее в этом pragma — это то, что вам не придётся прибегать к \x{....}, чтобы написать своё имя в родной кодировке. Поэтому не стесняйтесь помещать ваши строки в кавычки в вашей кодировке и в регулярных выражениях.
До Perl v5.22
Предикат был лексическим, но не на уровне блока, а на уровне скрипта. Только последний use encoding или no encoding имел значение, и он влиял на весь скрипт. Однако, предикат 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. Лучший способ избежать этой особенности — использовать этот предикат СРАЗУ после загрузки других модулей. Например:
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 должен разобрать скрипт перед применением этого предиката, такие кодировки, как Shift_JIS и Big-5, которые могут содержать
'\'(обратный слэш;\x5c) во втором байте, терпят неудачу, потому что второй байт может случайно экранировать символ цитирования, который следует за ним. -
tr/// -
Предикат кодировки работает путем декодирования строковых литералов в
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получают закодированный поток -
Они могут ожидать совершенно другого.
- литералы в регулярных выражениях, которые длиннее 127 байт
-
Для собственных многобайтовых кодировок (фиксированной или переменной длины) текущая реализация регулярных выражений может вводить ошибки перекодирования для литералов регулярных выражений, длиннее 127 байт.
- EBCDIC
-
Предикат кодирования не поддерживается на платформах EBCDIC.
format-
Этот предикат не работает хорошо с
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 вместо write() используется print().
В любом случае, само использование
formatвызывает сомнения в отношении символов Юникода, поскольку необходимо учитывать такие вещи, как ширина символа (т.е. двойная ширина для иероглифов) и направление (т.е. BIDI для арабского и иврита). - См. также "ЗАМЕЧАНИЯ"
ИСТОРИЯ
Этот предикат впервые появился в Perl v5.8.0. Он был улучшен в более поздних выпусках, как указано выше.
СМОТРИТЕ ТАКЖЕ
perlunicode, Encode, open, Filter::Util::Call,
Глава 15 Programming Perl (3rd Edition) Ларри Уолла, Тома Кристиансена, Джона Оранта; O'Reilly & Associates; ISBN 0-596-00027-8
© 1993–2023 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.38.0/encoding