写ref="/tag/2034/" style="color:#EB6E00;font-weight:bold;">Perl脚本时突然发现中文输出全是问号、方块,或者读取文件时报错 Wide character in print?别急,这不是Perl坏了,八成是编码没对上。
为啥Perl老在编码上栽跟头?
Perl本身不强制指定源码或数据的编码,它默认把字符串当字节流处理。你用UTF-8写的脚本,如果没明确告诉Perl“这段是UTF-8”,它就照单全收——结果就是中文变乱码,文件读写出错,正则匹配失灵。
第一招:脚本开头加这三行
在所有Perl脚本最顶部(#!/usr/bin/perl后面)加上:
use utf8;
use open ':std', ':encoding(UTF-8)';
use Encode qw(decode encode);
use utf8 告诉Perl:我的源代码是UTF-8写的;use open 让print和<STDIN>自动按UTF-8处理;Encode模块则是后续手动转码的备用武器。
第二招:读文件前先声明编码
比如读一个含中文的配置文件:
open my $fh, '<:encoding(UTF-8)', 'config.txt' or die $!;
while (my $line = <$fh>) {
chomp $line;
print "读到:$line\n";
}
close $fh;
注意 <:encoding(UTF-8) 这部分——漏掉它,Perl就把UTF-8字节当Latin-1读,中文直接崩。
第三招:遇到GBK/GB2312文件怎么办?
老系统导出的Excel CSV、Windows记事本存的txt,常是GBK编码。这时不能硬套UTF-8,得转:
use Encode qw(decode);
open my $fh, '<:bytes', 'old_report.txt' or die $!;
my $content = do { local $/; <$fh> };
close $fh;
my $utf8_str = decode('gbk', $content, Encode::FB_CROAK);
print $utf8_str;
FB_CROAK 表示遇到非法GBK字节就报错,比静默跳过更安全。
小提醒:终端也得配合
Linux/macOS下检查:echo $LANG,确保输出类似 zh_CN.UTF-8;Windows PowerShell里运行 [Console]::InputEncoding = [Text.UTF8Encoding]::new(),不然即使Perl输出正确,终端也显示不了中文。