如何从 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
隐含在 -C
和 PERL_UNICODE
中。 use open ':locale'
pragma 也值得一提,因为它是 -C
和 export 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?的主要内容,如果未能解决你的问题,请参考以下文章