编程文本处理 Perl 工程师

描述 Perl 中与 Unicode (UTF-8) 的工作特性。如何正确地读取、写入和处理不同编码的字符串,以及哪些细微差别常常导致错误?

用 Hintsage AI 助手通过面试

答案

Perl 最初并不是以 Unicode 为友好,处理 UTF-8 需要明确的指示。现代 Perl 能够将字符串作为内部抽象(utf8-flagged scalars)存储,但输入/输出操作需要特别关注。

正确的读取/写入:

  1. 设置 IO 层 (binmode, :encoding(UTF-8))。
  2. 如果源代码中包含 Unicode 文本,请使用 use utf8;
  3. 对于 STDIN、STDOUT 和文件,描述层:
open my $fh, '<:encoding(UTF-8)', 'myfile.txt' or die $!; binmode STDOUT, ':encoding(UTF-8)';

使用 Unicode 字符串:

  • 模块 Encode, utf8, open, charnames
  • 不要混合字节和带有 utf8 标志的字符串。
use Encode; my $bytes = encode('UTF-8', $string); # 获取字节 my $string = decode('UTF-8', $bytes); # 获取字符串

细微差别:

  • 没有“层”的文件以字节方式读取——长度/子字符串/正则操作会给出不正确的结果!
  • 与外部源(数据库、网络)交互时需要单独转换。
  • 甚至标准函数 print/read 也需要设置层。

陷阱问题

仅仅在脚本的开头添加 use utf8;,是否足以让所有输入/输出操作在 UTF-8 中进行?

答案: 不!指令 use utf8; 只是解读源代码中的 Unicode 文本。对于输入/输出,需要在 open 时或通过 binmode/open pragma 设置 IO 层!例如:

binmode STDOUT, ':encoding(UTF-8)'; open my $fh, '>:encoding(UTF-8)', $filename;

故事

在一个多语言项目中,接口在控制台输出时显示了乱码,因为 shell 以 UTF-8 工作,而 Perl 没有设置必要的 STDOUT 层(没有使用 binmode,只用 use utf8)。症状:长度和 substr 对于西里尔字母字符串给出了“乱码”结果。

故事

处理 XML 文件的脚本(UTF-8)在 open 时没有设置层,结果字符串是“脏”字节和 UTF-8 的混合。一些正则表达式根本没有奏效,而在尝试将数据序列化为 JSON 时,模块报出了关于“宽字符”的错误。

故事

在将 Perl 服务与 MySQL 客户端集成时,忽略了客户端的 utf8 配置,处理字节字符串。在与 web 界面的交汇处出现了缺陷——部分字符被破坏,部分请求则“破坏”了数据结构。通过 Encode 显式重编码和设置 'mysql_enable_utf8' 来解决这个问题。