代码之家  ›  专栏  ›  技术社区  ›  reencode

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

  •  0
  • reencode  · 技术社区  · 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 回复  |  直到 8 年前
        1
  •  6
  •   brian d foy    8 年前

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

    非中断空间的代码编号为U+00A0。在UTF-8下,它编码为两个八位字节\xC2和\xA0。所有代码在U+007F以上的东西在UTF-8下都有一个多八位组编码。U+007F下的所有内容实际上都是ASCII,所以ASCII就像UTF-8一样工作。

    如果你有UTF-8编码的文本和不间断的空间,只删除 \xA0 八重奏,有一首孤独的歌 \xC2 剩下的。这可能是一个问题,取决于它之后会发生什么。UTF-8旨在识别问题所在并自行纠正。它可以在下一个合法编码的字符处提取,并留下一个替换字符来标记错误。或者,该项目可以抱怨并放弃。

    当你使用character类时 [\xC2\xA0] ,我猜它在任何地方都能去除这些八位组中的任何一个。既然你没有报告任何其他错误,我猜 \xC2 不会出现在其他任何地方。否则,其他角色可能会改变。或者,您正在处理扩展ASCII并删除 \xC2 保留正确的拉丁-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入门,涵盖了很多内容。

    祝你好运