кодировка
СОДЕРЖАНИЕ
- НАЗВАНИЕ
- ПРЕДУПРЕЖДЕНИЕ
- СИНОПСИС
- ОПИСАНИЕ
- ПАРАМЕТРЫ
- ОСОБЕННОСТИ
- ПРИМЕР - 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 этого pragma (см. ниже).
Единственное законное использование этого pragma, скорее всего, будет только одно на файл, в начале, со scope файла, так как файл, скорее всего, будет написан только в одной кодировке. Дополнительные ограничения действуют в 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. Это для очень специализированных приложений и описано в "Под-pragma: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) существует и отлично от нуля, уровни PerlIO дляSTDINи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 можно задавать индивидуально параметрами pragma:
use encoding 'euc-tw', STDIN => 'greek' ...; В этом случае вы не можете опустить первый ENCNAME. STDIN => undef полностью отключает транскодирование ввода/вывода для этого файлового дескриптора.
Когда ${^UNICODE} (доступно начиная с v5.8.2) существует и отлично от нуля, эти параметры будут полностью игнорироваться. См. "${^UNICODE}" в perlvar и "-C" в perlrun для получения подробностей.
Под-pragma :locale
Начиная с версии v5.8.6, имя кодировки может быть :locale. Это означает, что кодировка берётся из текущего локали, а не жёстко задаётся pragma. Так как скрипт действительно может быть закодирован только в одной кодировке, этот параметр опасен. Он имеет смысл только если сам скрипт написан на ASCII, и все возможные локали, которые будут использоваться при выполнении скрипта, являются супермножествами ASCII. Это означает, что сам скрипт не изменяется, но файловые дескрипторы получают указанную кодировку, и операции, такие как chr и ord используют эту кодировку.
Логика определения, какую локаль использует :locale, такова:
-
Если платформа поддерживает интерфейс
langinfo(CODESET), используемый кодесет используется в качестве стандартной кодировки для pragma open. -
Если 1. не сработало, но мы находимся в pragma locale, переменные окружения
LC_ALLиLANG(в указанном порядке) проверяются на наличие кодировок (часть после ".", если есть), и если найдено, то используется в качестве стандартной кодировки для pragma open. -
Если 1. и 2. не сработали, переменные окружения
LC_ALLиLANG(в указанном порядке) проверяются на наличие чего-либо, похожего на UTF-8, и если найдено, то:utf8используется в качестве стандартной кодировки для pragma open.
Если ваши переменные окружения локали (LC_ALL, LC_CTYPE, LANG) содержат строки 'UTF-8' или 'UTF8' (регистронезависимое сравнение), стандартная кодировка ваших STDIN, STDOUT, и STDERR, и любого последующего открытого файла, равна UTF-8.
ОСОБЕННОСТИ
ПОБОЧНЫЕ ЭФФЕКТЫ
-
Если pragma
encodingнаходится в области видимости, то возвращаемые длины вычисляются на основе длины$/в символах Юникода, что не всегда совпадает с длиной$/в родной кодировке. -
Без этого pragma, если строки, работающие с байтами, и строки с данными символов Юникода, конкатенируются, новая строка будет создана путём декодирования байтовых строк как 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 (греческая малая буква йота с тоном) слева НЕ будет повышена до \x{3af} (Юникод греческая малая буква йота с тоном) из-за \x{100} слева. Не следует смешивать устаревшие данные и Юникод в одной строке.
Этот пragma также влияет на кодировку диапазона кодовых точек 0x80..0xFF: обычно символы в этом диапазоне остаются байтами по 8 бит (если только они не сочетаются с символами с кодовыми точками 0x100 или больше, в этом случае все символы должны быть закодированы в UTF-8), но если пragma encoding присутствует, то даже диапазон 0x80..0xFF всегда кодируется в UTF-8.
В конце концов, лучшая вещь в этом pragme заключается в том, что вам не нужно прибегать к \x{....}, чтобы просто написать ваше имя на родном языке. Поэтому смело помещайте свои строки в вашей кодировке в кавычки и регулярные выражения.
До Perl v5.22
Pragma был лексическим для каждого сценария, а не для каждого блока. Имел значение только последний use encoding или no encoding, и он влиял на весь сценарий. Однако, pragma 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 должен разобрать сценарий перед применением этого pragms, такие кодировки, как 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получают закодированный поток -
Они могут ожидать чего-то совершенно другого.
- литералы в регулярных выражениях, длина которых превышает 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–2021 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.34.0/encoding