我在我的 perl 程序中使用 utf8,我有以下代码行:
$$pstring =~ s/\xA0/ /g;
Run Code Online (Sandbox Code Playgroud)
这应该清除字符串中的不间断空格。
在 Ubuntu 16.04 和 perl v5.22.1 下这不是问题,但在 Ubuntu 14.04 和 v5.18.2 下我收到此错误:
格式错误的 UTF-8 字符(致命)
然后我检查了我试图匹配的字符串,发现那里有不间断的空格,可以被正则表达式删除
$$pstring =~ s/[\xC2\xA0]/ /g;
Run Code Online (Sandbox Code Playgroud)
但不是与
$$pstring =~ s/\xC2\xA0/ /g;
Run Code Online (Sandbox Code Playgroud)
我的问题是:最后两个之间有什么区别(为什么它只适用于括号),还有其他方法可以解决这个问题吗?
我的猜测是您正在处理原始的 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 class 时[\xC2\xA0],我猜它会在它们出现的任何地方摆脱这些八位字节中的任何一个。由于您没有报告任何其他错误,我猜这\xC2不会出现在其他任何地方。否则,其他字符可能会更改。或者,您正在处理扩展 ASCII 并删除\xC2正确的 Latin-1 编码的叶子。报告的替换数量是否s///等于不间断空格的数量(或两倍)?
如果您有 UTF-8 编码的文本,请将其阅读为 UTF-8:
open my $fh, '<:utf8', $filename or die ...
Run Code Online (Sandbox Code Playgroud)
阅读完数据后,不要担心编码。使用代码编号,Perl 会弄清楚。或者使用代码名称,以便未来的程序员无需查找字符就知道您在做什么:
my $string =~ s/\x{00A0}/ /g;
my $string =~ s/\N{NO-BREAK SPACE}/ /g;
Run Code Online (Sandbox Code Playgroud)
完成后,将其写为 UTF-8 文本:
open my $fh, '>:utf8', $filename or die ...
Run Code Online (Sandbox Code Playgroud)
最新的Learning Perl在后面有一本 Unicode 入门书,其中涵盖了相当多的内容。
祝你好运!