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

时间:2018-08-24 14:39:05

标签: regex perl 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/[\xC2\xA0]/ /g;

但不

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

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

1 个答案:

答案 0 :(得分:3)

我的猜测是您要处理的是原始的,UTF-8编码的字符串。您尚未显示如何获得它,也未说明为什么要这样做。一个小型完整的演示程序,它将显示您如何获得输入,如何更改输入以及最终抱怨什么,这将帮助人们发现问题。如果您将小型演示程序添加到您的问题中,我也许可以给出更好(甚至不同)的答案。

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

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

当您使用字符类[\xC2\xA0]时,我猜想它会消除它们出现的任何八位字节中的任何一个。由于您没有报告任何其他错误,因此我猜测\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入门,涵盖了很多内容。

祝你好运!