Perl脚本乱码?三招搞定常见编码问题

ref="/tag/2034/" style="color:#C468A7;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 openprint<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输出正确,终端也显示不了中文。