Raku Есть ли быстрый способ найти и удалить / заменить не-ASCII или неправильно сформированные символы utf8? - PullRequest
7 голосов
/ 23 февраля 2020

Я часто сталкиваюсь с искаженными символами utf-8, которые нарушают мои коды. Я прочитал некоторые (не все) связанные вопросы / ответы по stackoverflow, но ничего не указывало c на 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, которые являются модельными гражданами?

1 Ответ

9 голосов
/ 24 февраля 2020

Надеюсь, у кого-то будет лучший ответ. А пока ...


В вашем вопросе происходит несколько очень разных вещей.

Существует ли быстрый способ поиска и удаления / замены не-ASCII или неправильно сформированные символы utf8?

Предполагается, что это будет хороший, очевидный, довольно простой:

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

Этот должен декодировать так же, как обычный slurp делает, за исключением того, что вместо того, чтобы просто отказаться от декодирования при обнаружении «искаженного UTF-8», он должен просто заменить искаженные данные указанным вами символом замены и продолжить как можно лучше.

К сожалению (насколько я знаю) это не работает из-за ошибок в rakudo / moarvm, как обрисовано в общих чертах в моем ответе на декодирование с заменой, похоже, не работает .

Я не подал проблему в то время, когда я написал это ТАК. Ваш новый SO побудил меня подать два сообщения об ошибках:


Некоторые ответы приведены в ответах на сообщение об ошибке : Неверно сформированный UTF-8 .

Я вижу в ваших примерах repl, которые вы пробовали .decode('utf8-c8'). Это может быть вашей лучшей ставкой в ​​рамках raku в его нынешнем виде.


Если ничего из вышеперечисленного не поможет, я думаю, вы пока застряли с использованием внешнего инструмента для предварительной обработки файлов перед тем, как они попадут в raku. .

Существует ли предопределенный класс символов для всех хороших символов utf-8

Данные utf8 , а не символов. Это просто байты. Данные кодируют символов или, по крайней мере, должны, но очень важно держать в уме кодировки и символов .

Если вы знаете, как работают старомодные телеграммы, это так. Там есть сообщение в символах. И затем код Морзе для передачи. Это очень разные вещи.

Когда вы видите «Malformed UTF-8» или подобное, это означает, что декодер захлебывается какой-то частью данных (байтами). Они не имеют никакого смысла для этого как персонажи. Это как азбука Морзе, которая не следует правилам азбуки Морзе.

Такие данные в лучшем случае сбивают с толку и в худшем случае опасны. Стандарт Unicode требует, чтобы он был полностью исключен, прежде чем вы сможете сделать с ним что-нибудь .

Очевидным дружественным решением является замена дерьма на указанный пользователем символ замены как ты спросил. Напротив, класс символов регулярных выражений является и неправильным инструментом, и слишком поздним.

Пример: из REPL

Это еще один целый шарик воска.

Там есть:

  • Кодировка, используемая вашей (терминалом в вашей) локальной системе;

  • Символы, которые вы видите отрисованы , и указание курсора, когда вы используете вашу локальную систему;

  • Что находится в буфере вырезания / вставки при копировании с дисплея реплея;

  • Что ваш браузер делает с этим буфером, когда вы вставляете в окно редактирования вопрос SO;

  • Что серверы SO делают с этим содержимым окна редактирования, когда вы нажимаете Отправьте свой вопрос , и когда SO задает ваш вопрос;

  • Что моя локальная система, браузер, терминал, буфер вырезания / вставки и т. Д. c , когда я смотрю на ваш вопрос SO;

  • Et c.

Эта сложность существует, даже если обе наши системы и вы оба и я делаю то, что мы должны делать. Так что, конечно, что-то неправильно с курсором и другими проблемами, но я не собираюсь пытаться прибить это к этому ответу, потому что, в отличие от первой части вашего вопроса, на который я ответил выше, это не совсем делать с раку / до.

...