如何从 Perl 输出 UTF-8?

Posted

技术标签:

【中文标题】如何从 Perl 输出 UTF-8?【英文标题】:How can I output UTF-8 from Perl? 【发布时间】: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 的问题。我认为您应该调整终端的区域设置,如***.com/a/14405949/498634 所示。终端可能未设置为 UTF8,然后以 UTF8 写入 STDOUT 的数据将被错误编码 Great answer 如何使用utf8: 【参考方案1】:

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

binmode(STDOUT, ":utf8");

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

【讨论】:

我对此一无所知(我只是将 UTF8 放入数据库中,从未打印过)。 +1。 不客气。另请参阅另一个正确答案:***.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 "\x1815"';

或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 脚本输出正确的数据,然后才能担心终端仿真器如何解释它。

以上是关于如何从 Perl 输出 UTF-8?的主要内容,如果未能解决你的问题,请参考以下文章

当我的 Perl 程序在 cmd.exe 中输出 UTF-8 编码字符串时,为啥我会重复最后一个八位字节?

从 Perl 中的输出记录

如何在 Perl 中捕获输出和退出代码时执行外部脚本?

Perl - 从外部进程直接输出到标准输出(避免缓冲)

从 Perl 调用命令,需要查看输出

perl 在win下输出中文乱码问题