【问题标题】:How can I output UTF-8 from Perl?如何从 Perl 输出 UTF-8?
【发布时间】:2010-10-12 06:37:59
【问题描述】:

我正在尝试使用utf8 pragma 编写 Perl 脚本,但得到了意想不到的结果。我正在使用 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”。

【问题讨论】:

  • 也许它不是程序.. 我认为它是你的外壳或你的编辑器,它执行输出
  • 所有答案都正确回答了如何将其显式设置为 UTF8 的问题。我认为您应该调整终端的区域设置,如stackoverflow.com/a/14405949/498634 所示。终端可能未设置为 UTF8,然后以 UTF8 写入 STDOUT 的数据将被错误编码
  • Great answer 如何使用utf8:

标签: perl unicode utf-8


【解决方案1】:

use utf8; 不启用 Unicode 输出 - 它使您可以在程序中键入 Unicode。将此添加到程序中,在您的 print() 语句之前:

binmode(STDOUT, ":utf8");

看看是否有帮助。这应该使STDOUT 以 UTF-8 而不是普通的 ASCII 输出。

【讨论】:

  • 我对此一无所知(我只是将 UTF8 放入数据库中,从未打印过)。 +1。
  • 不客气。另请参阅另一个正确答案:stackoverflow.com/questions/627661/writing-perl-code-in-utf8/… 并记住,TMTOWTDI。还有@Paul - 如果您将 UTF-8 写入文件,您可能应该在该文件句柄上使用 binmode() 并使其“正确”UTF-8,但如果它有效..
  • 其他方式:open pragma(search.cpan.org/perldoc/open),-C 开关(perldoc.perl.org/perlrun.html#-C
  • FWIW 这就是原因:仅包含 latin1 (ISO-8859-1) 字符的字符串,尽管或多或少地存储在 utf8 中,但默认情况下将输出为 latin1。这样,即使使用支持 unicode 的 perl,来自 pre-unicode 时代的脚本仍然可以正常工作。
  • utf8 pragma 不允许您以 UNICODE 编写源代码,它强制您以 UNICODE 的 UTF-8(或 UTF-EBCDIC)编码理解您的源代码,这是一个重要的区别。
【解决方案2】:

您可以使用open pragma

例如。下面将 STDOUT、STDIN 和 STDERR 设置为使用 UTF-8....

use open qw/:std :utf8/;

【讨论】:

  • 顺便说一句...我给了你 +1。我认为 binmode(STDOUT, ':utf8') 在这种情况下可能更正确。 “使用开放”还有其他很好的用途,但我似乎无法找到如何将其设置为仅对 STDOUT 进行编码?
【解决方案3】:

TMTOWTDI,选择最适合您工作方式的方法。我使用环境方法,所以我不必考虑它。

environment

export PERL_UNICODE=SDL

command line

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";

open pragma:

use open ":encoding(utf8)";
use open IN => ":encoding(utf8)", OUT => ":utf8";

【讨论】:

  • +1 以获得全面的答案;请注意,SDL 隐含在 -CPERL_UNICODE 中。 use open ':locale' pragma 也值得一提,因为它是 -Cexport PER_UNICODE= 的脚本内等效项。假设您的环境的语言环境是基于 UTF8 的,这 3 个中的任何一个都将为您提供对所有输入和输出流(无论是文件还是 stdin/stdout/stderr)的 UTF8 支持。最后,要将 source 代码也视为 UTF8,请使用 use utf8; pragma。
  • perl -Mutf8 -CSDL -e '...' 允许使用/输出 UTF-8 以及,就像在 -e 中使用 UTF-8 文字一样,例如对于一个穷人的案件文件夹:perl -Mutf8 -CASDL -pe 'y/āáǎàēéěèīíǐìōóǒòūúǔùǖǘǚǜĀÁǍÀĒÉĚÈĪÍǏÌŌÓǑÒŪÚǓÙǕǗǙǛ/aaaaeeeeiiiioooouuuuüüüüAAAAEEEEIIIIOOOOUUUUÜÜÜÜ/'
【解决方案4】:

您还想说,您的代码中的字符串是 utf-8。见Why does modern Perl avoid UTF-8 by default?。所以不仅要设置PERL_UNICODE=SDAL,还要设置PERL5OPT=-Mutf8

【讨论】:

    【解决方案5】:

    谢谢,终于找到了一个不把 utf8::encode 全部覆盖代码的解决方案。 用于其他情况的合成和完成,例如在 utf8 中写入和读取文件,也可以与 utf8 中的 YAML 文件的 LoadFile 一起使用

    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
    

    【讨论】:

      【解决方案6】:

      在你的 shell 中做: $ env |grep 语言

      这可能表明您的 shell 没有使用 utf-8 语言环境。

      【讨论】:

      • 其实设置为utf-8。问题是我在没有将 binmode 设置为 utf-8 的情况下输出到 STDOUT;
      • 这将是一个正交问题。您需要 Perl 脚本输出正确的数据,然后才能担心终端仿真器如何解释它。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-21
      • 2016-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-06
      相关资源
      最近更新 更多