Фильтрация символов Microsoft 1252 из текстового файла ASCII, открытого в режиме utf8 в Perl - PullRequest
0 голосов
/ 21 октября 2011

У меня есть база данных текстовых документов разумного размера, в основном сохраненная в формате 8859, которые были собраны через веб-форму (с использованием скриптов Perl). До недавнего времени я согласовывал обычные 1252 символа (фигурные кавычки, апострофы и т. Д.) С простым набором регулярных выражений:

$line=~s/\x91/\&\#8216\;/g; # smart apostrophe left
$line=~s/\x92/\&\#8217\;/g; # smart apostrophe right

... и т. Д.

Однако, так как я решил, что должен использовать Unicode, и преобразовал все мои сценарии для чтения и вывода utf8 (который обрабатывает весь новый материал), регулярное выражение для этих (существующих) 1252 символов больше не работает и Мой вывод Perl html выводит буквально 4 символа: «\ x92», «\ x93» и т. д. (по крайней мере, так выглядит браузер в режиме utf8, загрузка (ftp не http) и открытие в текстовом редакторе (textpad) он отличается, остается один неопределенный символ, и при открытии выходного файла в Firefox по умолчанию (без заголовка типа содержимого) в режиме 8859 отображается правильный символ).

Новые прагмы utf8 в начале скрипта:

использовать CGI qw (-utf8); используйте open IO => ': utf8';

Я понимаю, что это происходит из-за того, что режим utf8 делает символы двухбайтовыми вместо однобайтовых, и применяется к этим символам в диапазоне от 0x80 до 0xff, прочитав статью об этом, но я не был мудрым, поскольку как их фильтровать. В идеале я знаю, что мне нужно заново сохранять все документы в режиме utf8 (так как база данных плоских файлов теперь содержит смесь 8859 и utf8), однако, прежде всего, мне понадобится какой-то фильтр, если я все равно это сделаю .

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

Если бы кто-нибудь мог предоставить мне решение для регулярных выражений, я был бы очень благодарен. Или какой-то другой метод. Я несколько недель рвал на себе волосы с различными попытками и неудачным взломом. Просто около 6 1252 символов, которые обычно нуждаются в замене, и с помощью метода фильтра я мог бы восстановить всю партию flippin в utf8 и забыть, что когда-либо было 1252 ...

Ответы [ 4 ]

2 голосов
/ 21 октября 2011

Кодировка :: FixLatin была специально написана, чтобы помочь исправить данные, разбитые так же, как ваши.

1 голос
/ 27 октября 2011

Вы также можете использовать поддержку Encode.pm для fallback .

use Encode qw[decode];

my $octets = "\x91 Foo \xE2\x98\xBA \x92";
my $string = decode('UTF-8', $octets, sub {
    my ($ordinal) = @_;
    return decode('Windows-1252', pack 'C', $ordinal);
});

printf "<%s>\n", 
  join ' ', map { sprintf 'U+%.4X', ord $_ } split //, $string;

Выход:

<U+2018 U+0020 U+0046 U+006F U+006F U+0020 U+263A U+0020 U+2019>
1 голос
/ 21 октября 2011

Ikegami уже упоминал модуль Encoding :: FixLatin .

Другой способ сделать это, если вы знаете, что каждая строка будет или UTF-8 или CP1252, но не является смесью обоих, - это прочитать ее как двоичную строку и сделать:

unless ( utf8::decode($string) ) {
    require Encode;
    $string = Encode::decode(cp1252 => $string);
}

По сравнению с Encoding :: FixLatin у этого есть два небольших преимущества: немного меньшая вероятность неверного истолкования текста CP1252 как UTF-8 (потому что вся строка должна быть допустимой UTF-8) и возможность замены CP1252 другим резервным вариантом. кодирование. Соответствующим недостатком является то, что этот код может возвращаться к CP1252 в строках, которые не совсем допустимы в UTF-8 по какой-то другой причине, например, потому что они были усечены в середине многобайтового символа.

0 голосов
/ 21 октября 2011

Вы перекодировали файлы данных? Если нет, то их открытие как UTF-8 не будет работать. Вы можете просто открыть их как

open $filehandle, '<:encoding(cp1252)', $filename or die ...;

и все (тм) должно работать.

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

...