今天客户发过来一个bug报告,说发送邮件时内容中书写はぁ~,收信时会显示成はち。 懂日文的朋友大概能明白,感叹词はぁ~怎么就变成了蜜蜂はち呢?

后来找到了原因。我们的邮件系统是用 Perl 写成的。其中有一个空格删除功能, 就是在显示时将邮件中的全角空格全部删除,其实现方法如下:

$body =~ s/ //g;

看起来似乎没有问题,但就是这条语句将はぁ~变成了はち。日文 euc-jp 编码下, 这几个字符串的编码如下:

| 字符串 | 编码 |h

はぁ~ A4CF A4A1 A1C1
はち A4CF A4C1
全角空格 A1A1

的后半个字符和的前半个字符恰好都是 A1,所以就被删除了,于是就出现了有意思的乱码现象。 修改方法也比较简单,只要正确识别出每个汉字的起止位置即可。

my $twoBytes   = '[\x8E\xA1-\xFE][\xA1-\xFE]';
my $threeBytes = '\x8F[\xA1-\xFE][\xA1-\xFE]';
while($body =~ s/\G(($twoBytes|$threeBytes|[\x00-\x7F])+?) /$1/g){};  # 识别汉字,如果汉字后面有空格则删除
$body =~ s/^ //g;        # 最后删除最开始处的全角空格