Raku 有没有一种快速的方法来查找和删除/替换非 ASCII 或格式错误的 utf8 字符?

lis*_*tor 8 regex char raku

我经常遇到格式错误的 utf-8 字符会破坏我的代码。我已经阅读了有关 stackoverflow 的一些(不是全部)相关问题/答案,但没有特定于 Raku/perl6。有没有一种快速的方法可以从字符串中删除这些讨厌的字符?“ https://docs.raku.org/language/regexes#Predefined_character_classes ”中的预定义字符类不会这样做:

示例:来自 REPL:

> say "â " ~~ /\w/ # you have to have a space following the "a" with "^" for it to work
?â?
> say "?" ~~ /\w/ # without the space, the character doesn't look normal
Malformed UTF-8 at line 1 col 6

> say "â ".chars # looks like 2 chars, but it says 1 char
1
> say "â ".comb.[0] # strange, the pesky char makes the space precede the cursor as I type
â
> say "â".comb.[0 ] # strange, the pesky char makes the space precede the cursor as I type
â
> say "â".comb.[0]  # there is a space following ']' or it won't work
â
> say "â".comb.[0 ] # very strange, must have space before ']'
â
> say "â".comb
(â)
> say "â".comb.[0] .ord # # same here, very strange, it makes space precede the cursor
226
> my $a = Buf.new(226)
Buf:0x<E2>
> say $a.decode
Malformed termination of UTF-8 string
  in block <unit> at <unknown file> line 1

> say $a.decode('utf8-c8')
xE2
> for @$a { say $_.chr; }
â
> say (@$a).elems
1
> say "â " ~~ / <alpha> / # again, must have space in the quote
?â?
 alpha => ?â?
> say "â " ~~ / <cntrl> /
Nil
Run Code Online (Sandbox Code Playgroud)

这是非常麻烦的。如何删除这些非 utf8 字符?对于所有良好的 utf-8 字符或作为模型公民的良好 ASCII 字符,是否有预定义的字符类?

rai*_*iph 9

希望有人会有更好的答案。同时...


您的问题中有几件非常不同的事情。

有没有一种快速的方法来查找和删除/替换非 ASCII 或格式错误的 utf8 字符?

应该有一个很好的,明显的,相当简单的:

say .decode: replacement => '?'
given $buf-that's-supposed-to-be-utf8
Run Code Online (Sandbox Code Playgroud)

应该以与普通代码相同的方式解码slurp,不同之处在于,当遇到“格式错误的 UTF-8”时,它应该只用您指定的替换字符替换格式错误的数据,并尽可能继续能够。

不幸的是(据我所知)由于 rakudo/moarvm 中的错误,这不起作用,如我的答案中所述,用替换解码似乎不起作用

我在写 SO 时没有提出问题。您的新 SO 提示我提交了两个错误报告:


错误消息的答案中给出了其他一些选项:Malformed UTF-8

我在您尝试过的 repl 示例中看到.decode('utf8-c8')。就目前而言,这可能是您在 raku 中的最佳选择。


如果以上都没有帮助,我认为您现在无法使用外部工具在文件到达 raku 之前对其进行预处理。

是否有适用于所有好的 utf-8 字符的预定义字符类

utf8 数据不是字符。这只是字节。数据对字符进行编码,或者至少它应该对字符进行编码,但是在您的脑海中将编码字符分开是非常重要的。

如果你知道老式电报的工作原理,就是这样。字符中有一条消息。然后是用于传输它的莫尔斯电码。它们是非常不同的东西。

当您看到“格式错误的 UTF-8”或类似内容时,这意味着解码器因数据的某些部分(字节)而阻塞。它们作为角色没有任何意义。这就像莫尔斯电码不遵循莫尔斯电码规则。

这样的数据充其量是令人困惑的废话,最坏的情况是危险的废话。Unicode 标准要求在您可以对其进行任何操作之前将其完全消除。

显而易见的友好解决方案是按照您的要求用用户指定的替换字符替换废话。相比之下,正则表达式字符类既是错误的工具,也为时已晚。

示例:来自 REPL

这是另一个完整的蜡球。

有:

  • 您的(您的)本地系统上的终端使用的编码;

  • 您看到的字符呈现,光标,当您使用本地系统的指示;

  • 从 repl 显示复制时,剪切/粘贴缓冲区中有什么;

  • 当您粘贴到 SO 问题的编辑窗口时,您的浏览器对该缓冲区做了什么;

  • 当您单击“发布您的问题”按钮以及当 SO 呈现您的问题时,SO 的服务器如何处理编辑窗口的内容;

  • 什么我的本地系统,浏览器,终端,剪切/粘贴缓冲区等等都当我看着你的SO问题所做的事。

  • 等等。

即使我们的系统和你我都在做我们应该做的事情,这种复杂性仍然存在。所以,当然,光标和其他问题有些不对劲,但我不会尝试用这个答案来确定这一点,因为与我在上面回答的问题的第一部分不同,这与 raku/do 没有关系.