Spec-Zone.ru › Perl 5.28

кодировка

СОДЕРЖАНИЕ

  • НАЗВАНИЕ
  • ПРЕДУПРЕЖДЕНИЕ
  • СИНОПСИС
  • ОПИСАНИЕ
  • ПАРАМЕТРЫ
    • Указание STDIN и/или STDOUT индивидуально
    • Под-псевдоним :locale
  • ЗАМЕЧАНИЯ
    • ПОБОЧНЫЕ ЭФФЕКТЫ
    • НЕ СМЕШИВАЙТЕ НЕСКОЛЬКО КОДИРОВОК
    • До Perl версии 5.22
    • До версии Encode 1.87
    • До Perl версии 5.8.1
  • ПРИМЕР - 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) существует и не равно нулю, уровни 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, например, вы всё равно можете пробовать примеры из главы 15 Programming 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 выглядит следующим образом:

  1. Если платформа поддерживает интерфейс langinfo(CODESET), используемый кодесет используется в качестве кодировки по умолчанию для открывающего псевдонима.

  2. Если 1. не сработало, но мы находимся под псевдонимом locale, переменные окружения LC_ALL и LANG (в этом порядке) проверяются на соответствие кодировкам (часть после ".", если есть), и если какая-либо найдена, она используется в качестве кодировки по умолчанию для открывающего псевдонима.

  3. Если 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API