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

63

Если я запустил следующую программу 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. У меня такая же проблема, если это файл, а не один лайнер в командной строке.

  • 3
    "Почему это не работает?" Это делает работу, но это был мой опыт работы с Unicode , что есть много очень сломанные программы там , которые выглядят как они работают. Когда вы исправляете одну вещь, делая код немного менее неправильным, результаты кажутся намного хуже. Только когда вы исправляете последнюю часть, все снова выглядит хорошо.
  • 0
    Обычно исправляется установкой дескриптора вывода в binmode с правильной кодировкой ... albertech.blogspot.com/2017/04/…
Теги:
unicode
utf-8

6 ответов

81
Лучший ответ

Без 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";'
鸡

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

  • 0
    Как пишется -Mutf8 если не в одном вкладыше Perl?
  • 0
    @LeiYang: use utf8;
58

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

use open ':std', ':encoding(UTF-8)';
  • 0
    Спасибо, это хорошо работает для программ, хранящихся в файлах, в отличие от однострочных в командной строке, которые рассматриваются в ответе @ DaveCross.
11

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

binmode STDOUT, ":utf8";
11

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

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

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

3

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

perl -CS filename.

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

  • 0
    только это помогло
1

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

use utf8;

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

  • 1
    Нет, это не то, что вызывало ошибку. Код был правильно закодирован как UTF8, но дескриптор выходного файла не знал, что это так.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню