Unicode字符串上的正则表达式由调试器解释为预期,但不是由程序解释

时间:2013-04-25 22:51:08

标签: regex perl unicode utf-8

这是 - 减少到最小 - 我用来读取和解释一些UTF8文本文件的程序:

use 5.012;
use utf8;
binmode STDIN, ':utf8';
binmode STDOUT, ':utf8';

while (<>) {
    chomp;
    if ($_ =~ /BOLETIM DE ANÁLISE N/) {print "Boletim\n";}
    if ($_ =~ /DADOS REFERENTES A AMOSTRA/) {print "Dados\n";}
}

输入文件包含应该同时满足两个正则表达式的行,并且我使用TextWrangler验证该文件确实是UTF-8,带有Unix端线。但是,程序仅识别第二个,不包含重音字符。

奇怪(至少对我而言)是当我在调试器中并运行相同的行时

    x if ($_ =~ /BOLETIM DE ANÁLISE N/) {print "Boletim\n";}

当$ _是字符串'BOLETIM DE ANÁLISE N° 274734/2011-0 '时,正则表达式触发并打印“Boletim”。

为什么调试器和程序有不同的行为?

非常感谢提前

阿德

PS我在Mac Os X 10.7.5和Perl v5.12.4上。

1 个答案:

答案 0 :(得分:2)

您没有正确解码UTF-8文件。

capital-A-acute 的Unicode值为1930xC1。匹配AN(.*)LISE的结果显示此字符具有多字节表示形式,从195开始。此字符的UTF-8编码为C3 81(或十进制的195 129),因此您要查看两个单字节字符而不是单个字节C1

您可以通过编写

来确认
print join ' ', map sprintf('%02X', ord), split //, $1;
匹配操作后

。您将获得C3 81

您设置STDINSTDOUT以使用utf8使用binmode图层,但<>运算符从ARGV文件句柄中读取除非@ARGV为空。

我建议你写

binmode ARGV, ':utf8';

还解码从ARGV读取的数据。那一切都应该好。