匹配不间断空格时格式错误的 UTF-8 字符



我在我的perl程序中使用utf8,我得到了以下代码行:

$$pstring =~ s/xA0/ /g; 

这应该从字符串中清除不间断的空格。

在 Ubuntu 16.04 和 perl v5.22.1 下,这不是问题,但在 Ubuntu 14.04 和 v5.18.2 下,我收到此错误:

格式错误的 UTF-8 字符(致命(

然后我检查了我试图匹配的字符串,发现里面有不间断的空格,可以通过正则表达式删除

$$pstring =~ s/[xC2xA0]/ /g;

但不是

$$pstring =~ s/xC2xA0/ /g;

我的问题是:最后两个有什么区别(为什么它仅适用于括号(,有没有另一种解决方法?

我的猜测是你正在处理一个原始的 UTF-8 编码字符串。你还没有展示你是如何得到它的,或者说你为什么要这样做。一个小型而完整的演示程序,展示您如何获得输入,如何更改它以及最终抱怨的内容,将帮助人们找到问题。如果你把这个小的演示程序添加到你的问题中,我也许能够给出一个更好(甚至不同(的答案。

不间断空格的代码编号为 U+00A0。在 UTF-8 下,它编码为两个八位字节 \xC2 和 \xA0。代码号高于 U+007F 的所有内容都具有 UTF-8 下的多八位字节编码。U+007F 下的所有内容实际上都只是 ASCII,因此 ASCII 作为 UTF-8 工作。

如果您有带有不间断空格的 UTF-8 编码文本,并且只删除xA0八位字节,则剩下一个孤独的xC2。根据之后的情况,这可能是一个问题。UTF-8 旨在识别问题所在并自行纠正。它可以在下一个合法编码的字符上拾取,并留下替换字符来标记错误。或者,程序可以抱怨并放弃。

当您使用字符类[xC2xA0]时,我猜它会在它们出现的任何地方摆脱这些八位字节中的任何一个。由于您没有报告任何其他错误,我猜xC2不会出现在其他任何地方。否则,其他字符可能会更改。或者,您正在处理扩展的 ASCII,删除xC2会留下正确的 Latin-1 编码。s///报告的替换数是否等于不间断空格的数量(或两倍(?

如果您有 UTF-8 编码的文本,请将其读为 UTF-8:

open my $fh, '<:utf8', $filename or die ...

读取数据后,不必担心编码。使用代码编号,Perl会弄清楚的。或者使用代号,以便未来的程序员知道你在做什么,而无需查找字符:

my $string =~ s/x{00A0}/ /g;
my $string =~ s/N{NO-BREAK SPACE}/ /g;

完成后,将其编写为 UTF-8 文本:

open my $fh, '>:utf8', $filename or die ...

最新的Learning Perl后面有一个Unicode入门书,涵盖了相当多的内容。

祝你好运!

最新更新