кодировка
СОДЕРЖАНИЕ
- НАЗВАНИЕ
- ПРЕДУПРЕЖДЕНИЕ
- СИНОПСИС
- ОПИСАНИЕ
- ПАРАМЕТРЫ
- ЗАМЕЧАНИЯ
- ПРИМЕР - 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 данного псевдонима (см. ниже).
Единственное законное использование этого псевдонима, скорее всего, одно на файл, в начале, со сферой действия файла, так как файл, вероятно, будет написан только в одной кодировке. Дополнительные ограничения действуют в Perl-версиях до 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), используемый кодесет используется в качестве кодировки по умолчанию для открывающего псевдонима. -
Если 1. не сработало, но мы находимся под псевдонимом locale, переменные окружения
LC_ALLиLANG(в этом порядке) проверяются на соответствие кодировкам (часть после ".", если есть), и если какая-либо найдена, она используется в качестве кодировки по умолчанию для открывающего псевдонима. -
Если 1. и 2. не сработали, переменные окружения
LC_ALLиLANG(в этом порядке) проверяются на соответствие чему-либо, похожему на UTF-8, и если какое-либо найдено,:utf8используется в качестве кодировки по умолчанию для открывающего псевдонима.
Если ваши переменные окружения языка (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} слева. Вы не должны смешивать старые данные и Юникод в одной строке.
Этот прагма также влияет на кодировку диапазона кодовых точек 0x80..0xFF: обычно символы в этом диапазоне остаются байтами по 8 бит (если они не комбинируются с символами с кодовыми точками 0x100 или больше, в этом случае все символы должны быть закодированы в UTF-8), но если присутствует прагма encoding, то даже диапазон 0x80..0xFF всегда кодируется в UTF-8.
В конце концов, самое лучшее в этом прагме то, что вам не нужно прибегать к \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() происходит failure print().
В любом случае, само использование
formatсомнительно, когда речь идёт о символах Юникода, так как нужно учитывать такие вещи, как ширина символа (например, двойная ширина для идеограмм) и направления (например, BIDI для арабского и иврита). - См. также "CAVEATS"
ИСТОРИЯ
Этот прагма впервые появился в 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.28.3/encoding