Как я могу вывести UTF-8 из Perl?

90

Я пытаюсь написать Perl script, используя прагму "utf8", и получаю неожиданные результаты. Я использую Mac OS X 10.5 (Leopard), и я редактирую TextMate. Все мои настройки как для моего редактора, так и для операционной системы по умолчанию предназначены для записи файлов в формате utf-8.

Однако, когда я ввожу следующее в текстовый файл, сохраните его как ".pl" и выполнив его, я получаю дружественный "алмаз с вопросительным знаком" вместо символов, отличных от ASCII.

#!/usr/bin/env perl -w

use strict;
use utf8;

my $str = 'Çirçös';
print( "$str\n" );

Любая идея, что я делаю неправильно? Я ожидаю получить "Çirçös" на выходе, но вместо этого получаю "ir s".

  • 1
    Может быть, это не программа .. Я думаю, что это ваша оболочка или ваш редактор, который делает вывод
  • 0
    Все ответы правильно отвечают на ваш вопрос, как явно установить UTF8. Я думаю, что вы должны быть настроены на языковые настройки вашего терминала, как показано в stackoverflow.com/a/14405949/498634 . Возможно, терминал не установлен в UTF8, и тогда данные, записанные в STDOUT в UTF8, будут закодированы неправильно !
Теги:
unicode
utf-8

7 ответов

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

use utf8; не включает выход Unicode - он позволяет вводить Unicode в вашей программе. Добавьте это в программу перед оператором print():

binmode(STDOUT, ":utf8");

Посмотрите, поможет ли это. Это должно сделать вывод STDOUT в UTF-8 вместо обычного ASCII.

  • 0
    Я не знал об этом (я только помещал UTF8 в базу данных, никогда не печатая его). +1.
  • 0
    Это сработало, Крис. Спасибо!
Показать ещё 8 комментариев
72

Вы можете использовать открытую прагму.

Например, ниже устанавливает STDOUT, STDIN и STDERR для использования UTF-8....

use open qw/:std :utf8/;
  • 1
    Также хорошо. Я бы +1, но у меня нет голосов на сегодня.
  • 1
    Кстати ... я дал тебе +1. Я думаю, что binmode (STDOUT, ': utf8'), вероятно, более корректен в этой ситуации. У «use open» есть и другие хорошие применения, но я не могу найти, как вы можете настроить его только для кодирования STDOUT?
57

TMTOWTDI, выберите метод, который наилучшим образом соответствует тому, как вы работаете. Я использую метод среды, поэтому мне не нужно об этом думать.

В среде :

export PERL_UNICODE=SDL

в командной строке :

perl -CSDL -le 'print "\x{1815}"';

или binmode:

binmode(STDOUT, ":utf8");          #treat as if it is UTF-8
binmode(STDIN, ":encoding(utf8)"); #actually check if it is UTF-8

или PerlIO:

open my $fh, ">:utf8", $filename
    or die "could not open $filename: $!\n";

open my $fh, "<:encoding(utf-8)", $filename
    or die "could not open $filename: $!\n";

или с открытой прагмой:

use open ":encoding(utf8)";
use open IN => ":encoding(utf8)", OUT => ":utf8";
  • 1
    -CSDL работал для меня, где только binmode не работал.
  • 1
    +1 за исчерпывающий ответ; обратите внимание, что SDL подразумевается как с -C и с PERL_UNICODE . Также стоит упомянуть прагму use open ':locale' , потому что она является эквивалентом -C в сценарии и export PER_UNICODE= . Любой из этих 3 даст вам поддержку UTF8 для всех входных и выходных потоков (файлов или stdin / stdout / stderr), при условии, что локаль вашей среды основана на UTF8. Наконец, чтобы также рассматривать исходный код как UTF8, use utf8; Прагма.
Показать ещё 1 комментарий
1

Вы также хотите сказать, что строки в вашем коде - utf-8. См. Почему современный Perl предотвращает UTF-8 по умолчанию?. Поэтому установите не только PERL_UNICODE=SDAL, но также PERL5OPT=-Mutf8.

0

Спасибо, наконец, получил решение не поместить utf8:: encode весь код. Синтезировать и завершить для других случаев, таких как запись и чтение файлов в utf8, а также работает с LoadFile файла YAML в utf8

use utf8;
use open ':encoding(utf8)';
binmode(STDOUT, ":utf8");

open(FH, ">test.txt"); 
print FH "something éá";

use YAML qw(LoadFile Dump);
my $PUBS = LoadFile("cache.yaml");
my $f = "2917";
my $ref = $PUBS->{$f};
print "$f \"".$ref->{name}."\" ". $ref->{primary_uri}." ";

где cache.yaml:

---
2917:
  id: 2917
  name: Semanário
  primary_uri: 2917.xml
-2

сделайте в своей оболочке: $ env | grep LANG

Это, вероятно, покажет, что ваша оболочка не использует локаль utf-8.

  • 0
    На самом деле, он был установлен на UTF-8. Проблема заключалась в том, что я выводил в STDOUT без установки binmode в utf-8;
  • 2
    Это было бы ортогональной проблемой. Вам нужен ваш Perl-скрипт для вывода правильных данных, прежде чем вы будете беспокоиться о том, как ваш эмулятор терминала интерпретирует их.
-3

Перенаправить вывод в текстовый файл и попробовать его в редакторе. Если он отображается нормально, тогда ваш терминал неисправен.

Ещё вопросы

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