Использование 'use utf8;' дает мне "Широкий характер в печати",

Если я запустил следующую программу Perl:

perl -e 'use utf8; print "鸡\n";'

Я получаю это предупреждение:

Wide character in print at -e line 1.

Если я запустил эту программу Perl:

perl -e 'print "鸡\n";'

Я не получаю предупреждение.

Я думал, что use utf8 требуется использовать символы UTF-8 в Perl script. Почему это не работает и как я могу это исправить? Я использую Perl 5.16.2. У меня такая же проблема, если это файл, а не один лайнер в командной строке.

Ответ 1

Без use utf8 Perl интерпретирует вашу строку как последовательность однобайтовых символов. В вашей строке есть четыре байта:

$ perl -E 'say join ":", map { ord } split //, "鸡\n";'
233:184:161:10

Первые три байта составляют ваш символ, последний - строка.

Вызов print вызывает эти четыре символа в STDOUT. Затем ваша консоль работает над тем, как отображать эти символы. Если ваша консоль настроена на использование UTF8, она будет интерпретировать эти три байта как ваш единственный символ, и это то, что отображается.

Если мы добавим модуль utf8, все будет по-другому. В этом случае Perl интерпретирует вашу строку как два символа.

$ perl -Mutf8 -E 'say join ":", map { ord } split //, "鸡\n";'
40481:10

По умолчанию слой Perl IO предполагает, что он работает с однобайтовыми символами. Поэтому, когда вы пытаетесь напечатать многобайтовый символ, Perl считает, что что-то не так и дает вам предупреждение. Как всегда, вы можете получить больше объяснений этой ошибки, включив use diagnostics. Он скажет это:

(S utf8) Perl встретил широкий символ ( > 255), когда он не ожидал один. Это предупреждение по умолчанию включено для ввода-вывода (например, для печати). Простейший чтобы успокоить это предупреждение, просто добавьте слой: utf8 к выход, например. binmode STDOUT, ': utf8'. Другой способ отключить предупреждение заключается в том, чтобы не добавлять предупреждения "utf8"; но это часто ближе к мошенничество. В общем, вы должны явно отмечать filehandle с кодировкой, см. open и perlfunc/binmode.

Как указывали другие, вам нужно сказать Perl принять многобайтовый вывод. Существует много способов сделать это (см. Perl Unicode Tutorial для некоторых примеров). Один из самых простых способов - использовать флаг командной строки -CS, который сообщает трем стандартным дескрипторам файлов (STDIN, STDOUT и STDERR) для работы с UTF8.

$ perl -Mutf8 -e 'print "鸡\n";'
Wide character in print at -e line 1.
鸡

против

$ perl -Mutf8 -CS -e 'print "鸡\n";'
鸡

Юникод - большая и сложная область. Как вы видели, многие простые программы, похоже, поступают правильно, но по неправильным причинам. Когда вы начнете исправлять часть программы, ситуация будет часто ухудшаться, пока вы не исправили всю программу.

Ответ 2

Все use utf8; это говорит Perl, что исходный код кодируется с использованием UTF-8. Вам нужно указать Perl, как кодировать текст:

use open ':std', ':encoding(UTF-8)';

Ответ 3

Вы можете приблизиться к "просто делать utf8 всюду", используя модуль CPAN utf8::all.

perl -Mutf8::all -e 'print "鸡\n";'

Когда print получает то, что он не может распечатать (символ больше 255, если не указан слой :encoding), предполагается, что вы хотите его кодировать с использованием UTF-8. Он делает это, после предупреждения о проблеме.

Ответ 4

Кодировать весь стандартный вывод как UTF-8:

binmode STDOUT, ":utf8";

Ответ 5

Вы можете использовать это,

perl -CS filename.

Он также завершит эту ошибку.

Ответ 6

На испанском языке вы можете найти эту ошибку, если вы начинаете использовать:

use utf8;

Ваша кодировка редактора находится в другой кодировке. Так что вы видите в редакторе не то, что делает Perl. Чтобы решить эту ошибку, просто измените кодировку редактора на Unicode/UTF-8.