Неверно сформированный символ UTF-8 при сопоставлении с неразрывным пробелом - PullRequest
0 голосов
/ 24 августа 2018

Я использую utf8 в моей программе Perl, и у меня есть следующая строка кода:

$$pstring =~ s/\xA0/ /g; 

, который должен убрать неразрывные пробелы из строки.

В Ubuntu 16.04 и perl v5.22.1 это не проблема, но в Ubuntu 14.04 и v5.18.2 я получаю эту ошибку:

Неверно сформированный символ UTF-8 (смертельно)

Затем я проверил строку, которую пытался сопоставить, и обнаружил, что там есть неразрывные пробелы, которые могут быть удалены с помощью регулярного выражения

$$pstring =~ s/[\xC2\xA0]/ /g;

но не с

$$pstring =~ s/\xC2\xA0/ /g;

У меня вопрос: в чем разница между двумя последними (почему он работает только в скобках) и есть ли другой способ решения этой проблемы?

1 Ответ

0 голосов
/ 24 августа 2018

Я предполагаю, что вы имеете дело с необработанной строкой в ​​кодировке UTF-8. Вы не показали, как вы это получили, и не сказали, почему вы хотите это сделать. Небольшая и полная демонстрационная программа, которая показывает, как вы получаете информацию, как вы ее изменяете и на что в конечном итоге жалуется, поможет людям найти проблему. Если вы добавите эту небольшую демонстрационную программу к своему вопросу, я смогу дать лучший (или даже другой) ответ.

Неразрывный пробел имеет кодовый номер U + 00A0. Под UTF-8 он кодирует два октета \ xC2 и \ xA0. Все с кодом выше U + 007F имеет многооктетное кодирование в UTF-8. Все в U + 007F на самом деле просто ASCII, поэтому ASCII работает как UTF-8.

Если у вас есть текст в кодировке UTF-8 с неразрывным пробелом и вы удалите только октет \xA0, остается одинокий \xC2. В зависимости от того, что последует за ним, это может быть проблемой. UTF-8 предназначен для того, чтобы распознавать проблему и исправлять ее. Он может подобрать следующий юридически закодированный символ и оставить символ подстановки для обозначения ошибки. Или программа может пожаловаться и сдаться.

Когда вы используете класс символов [\xC2\xA0], я предполагаю, что он избавляется от любого из этих октетов везде, где они появляются. Поскольку вы не сообщаете о других ошибках, я предполагаю, что \xC2 больше нигде не появляется. В противном случае другие символы могут измениться. Или вы имеете дело с расширенным ASCII, и удаление \xC2 оставляет правильную кодировку Latin-1. Соответствует ли число замен, сообщенных s///, количеству неразрывных пробелов (или удваивает его)?

Если у вас есть кодированный в UTF-8 текст, прочитайте его как UTF-8:

open my $fh, '<:utf8', $filename or die ...

После прочтения данных не беспокойтесь о кодировке. Используйте кодовые номера, и Perl выяснит это. Или используйте кодовые имена, чтобы будущие программисты знали, что вы делаете, не ища символа:

my $string =~ s/\x{00A0}/ /g;
my $string =~ s/\N{NO-BREAK SPACE}/ /g;

Когда вы закончите, напишите его в виде текста UTF-8:

open my $fh, '>:utf8', $filename or die ...

В новейшем Learning Perl имеется задник Unicode, который охватывает довольно много этого.

Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...