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

问题描述

我经常遇到破坏我的代码的格式错误的 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

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

标签: regexcharraku

解决方案


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


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

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

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

say .decode: replacement => '�'
given $buf-that's-supposed-to-be-utf8

应该以与plain相同的方式解码slurp,除了在遇到“Malformed 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 无关.


推荐阅读