Как удалить непечатаемые / невидимые символы в рубине?

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

Например, у них может быть безразрывное пространство нулевой ширины в середину строки. Например, при синтаксическом анализе файла .po одной проблемной частью была строка "he is a man of god" в середине файла. Хотя все кажется правильным, проверка с помощью irb показывает:

 "he is a man of god".codepoints
 => [104, 101, 32, 105, 115, 32, 97, 32, 65279, 109, 97, 110, 32, 111, 102, 32, 103, 111, 100] 

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

Мой текущий подход состоит в том, чтобы удалить всех персонажей, которых я нашел злыми, по-настоящему вонючим:

text = (text.codepoints - CODEPOINTS_BlACKLIST).pack("U*")

Больше всего я следил за этот пост, который привел меня к :print: опции регулярных выражений. Однако мне это не пошло:

"m".scan(/[[:print:]]/).join.codepoints
 => [65279, 109] 

поэтому возникает вопрос: Как удалить все непечатаемые символы из строки в рубине?


person fotanus    schedule 13.05.2013    source источник
comment
Было бы очень полезно, если бы вы показали больше исходных и пробных строк с символами, которые вы пытаетесь обработать. Текущий образец не очень помогает при попытке определить кодовый набор или другие значения, с которыми вы сталкиваетесь.   -  person the Tin Man    schedule 14.05.2013
comment
@theTinMan Спасибо, я отредактировал вопрос с более подробной информацией. Я считаю, что кодировка - UTF-8, но у меня не всегда есть информация, у меня много файлов без спецификации. Я полагаю, что это хотя бы частично Unicode, глядя на китайский перевод.   -  person fotanus    schedule 14.05.2013
comment
В Ruby есть метод для String с именем dump, который создает новую строку с удаленными непечатаемыми символами и экранированием специальных символов. Документы для String # dump Ruby 2.3. 0, но я могу подтвердить, что это есть в документации уже в 1.8.7.   -  person Aaron    schedule 18.11.2016


Ответы (3)


попробуй это:

>>"aaa\f\d\x00abcd".gsub(/[^[:print:]]/,'.')
=>"aaa.d.abcd"
person snowytoxa    schedule 17.07.2014
comment
К сожалению, это также удаляет новые строки. - person LouieGeetoo; 16.12.2020

Ruby может помочь вам преобразовать один набор многобайтовых символов в другой. Проверьте результаты поиска, а также прочитайте _ 1_.

Кроме того, ваш друг - Iconv Ruby.

Наконец, Джеймс Грей написал серию статей, в которых подробно рассматривается этот вопрос. деталь.

Одна из вещей, которые вы можете сделать с помощью этих инструментов, - это сказать им, чтобы они перекодировали визуально похожий символ или полностью игнорировали их.

Работа с альтернативными наборами символов - одна из самых ... раздражающих вещей, которые мне когда-либо приходилось делать, потому что файлы могут содержать что угодно, но быть помечены как текст. Вы можете этого не ожидать, и тогда ваш код умирает или начинает выдавать ошибки, потому что люди настолько изобретательны, когда придумывают способы вставки альтернативных символов в контент.

person the Tin Man    schedule 13.05.2013
comment
Сдался ... Я думаю, что нет лучшего способа обрабатывать искаженные файлы. Однако я принимаю ваш ответ, потому что это хороший ориентир для людей, которые в конечном итоге получают хорошо сформированные файлы. - person fotanus; 18.05.2013
comment
Ни одна из этих ссылок сейчас не работает :( - person Luna Lovegood; 25.04.2019
comment
@Surya, спасибо, да пара сломалась, но не все. Способ SO - поддерживать сайт. Вы можете помочь, отправив правки, чтобы исправить такие проблемы, как неработающие ссылки. См. Как работают предлагаемые изменения. - person the Tin Man; 23.05.2019
comment
Спасибо, что обратили мое внимание на эту функцию. - person Luna Lovegood; 23.05.2019

Codepoint 65279 - это беспрерывный пробел нулевой ширины. Обычно он используется как метка порядка байтов (BOM).

Вы можете удалить его из строки с помощью:

my_new_string = my_old_string.gsub!("\xEF\xBB\xBF".force_encoding("UTF-8"), '')

Быстрый способ проверить, есть ли у вас какие-либо невидимые символы, - это проверить длину строки, если она больше, чем вы можете видеть в IRB, вы это делаете.

person Jamie Buchanan    schedule 28.07.2020