ChatGPT解决这个技术问题 Extra ChatGPT

如何从 Perl 输出 UTF-8?

我正在尝试使用 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

C
Chris Lutz

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)编码理解您的源代码,这是一个重要的区别。
A
AndyG

您可以使用 open pragma

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

use open qw/:std :utf8/;

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

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

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


S
Sérgio

谢谢,终于找到了一个解决方案,不要把 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

n
nxadm

在你的 shell 中做: $ env |grep LANG

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


实际上,它被设置为 utf-8。问题是我在没有将 binmode 设置为 utf-8 的情况下输出到 STDOUT;
这将是一个正交问题。您需要您的 Perl 脚本输出正确的数据,然后您才能担心终端仿真器如何解释它。