Удалить спецификацию из строки с помощью Perl

У меня следующая проблема: я читаю из текстового файла UTF-8 (и я говорю Perl, что делаю это с помощью ": encoding (utf-8)").

Файл в шестнадцатеричной программе просмотра выглядит так: EF BB BF 43 6F 6E 66 65 72 65 6E 63 65

При печати это переводится как «Конференция». Я понимаю, что "широкий характер", о котором меня предупреждают, - это спецификация. Я хочу избавиться от него (не из-за предупреждения, а потому, что он испортил сравнение строк, которое я предприму позже).

Поэтому я попытался удалить его с помощью следующего кода, но у меня ничего не вышло:

$ line = ~ s / ^ \ xEF \ xBB \ xBF //;

Может ли кто-нибудь просветить меня относительно того, как удалить спецификацию UTF-8 из строки, которую я получил, прочитав первую строку файла UTF-8?

Спасибо!


person user1769925    schedule 24.06.2014    source источник
comment
Если у вас правильно настроена кодировка вывода, нет необходимости удалять спецификацию, потому что пространство нулевой ширины не повлияет на результат.   -  person Borodin    schedule 24.06.2014


Ответы (4)


EF BB BF - это кодировка UTF-8 спецификации, но вы ее декодировали, поэтому вы должны искать ее декодированную форму. Спецификация - это ПРОБЕЛ БЕЗ РАЗРЫВА НУЛЕВОЙ ШИРИНЫ (U + FEFF), используемый в начале файла, поэтому подойдет любое из следующих действий:

s/^\x{FEFF}//;
s/^\N{U+FEFF}//;
s/^\N{ZERO WIDTH NO-BREAK SPACE}//;
s/^\N{BOM}//;   # Convenient alias

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

Вы получаете широкий символ, потому что вы забыли добавить слой :encoding в дескриптор выходного файла. Следующее добавляет :encoding(UTF-8) к STDIN, STDOUT, STDERR и делает его значением по умолчанию для open().

use open ':std', ':encoding(UTF-8)';
person ikegami    schedule 24.06.2014
comment
чтобы использовать сокращение, мне нужно было добавить use charnames ': full'; - person user1769925; 24.06.2014
comment
Я думаю, что для \N{...} нужна 5.12 Я думаю, что для \N{BOM} нужна 5.14. use charnames ':full'; требуется до 5.16. - person ikegami; 24.06.2014
comment
@ user1769925: Обратите внимание, что проблема в том, что вы декодировали данные из файла (из-за вашего :encoding(utf-8) открытого режима), поэтому первым символом входной строки является Unicode U+FEFF , но вы используете необработанные байты данных в кодировке UTF-8 в своей замене - person Borodin; 24.06.2014
comment
Эти решения вызывали ошибки времени компиляции, пока я не добавил этот код: use charnames: full ;. После этого решения по-прежнему не внесли никаких изменений. Что в конечном итоге решило эту проблему для меня: использование Encode; my $ value = decode ('UTF-8', $ значение); $ value = ~ s / \ N {U + FEFF} //; - person HoldOffHunger; 30.09.2016
comment
@HoldOffHunger, уже упоминалось, что в старых версиях Perl нужен use charnames ":full";. /// Ключевой частью вопроса является эквивалент того, что decode('UTF-8', $value) уже было выполнено - их код работал бы, если бы они еще не декодировали текст - поэтому добавление decode('UTF-8', $value) здесь было бы неправильным. - person ikegami; 30.09.2016

Чтобы обезвредить спецификацию, вы должны знать, что это не 3 символа, это 1 в UTF (U + FEFF):

s/^\x{FEFF}//;
person Eugene K    schedule 24.06.2014
comment
le upvote за то, что он назвал его взрывчатым веществом. - person Alexej Magura; 10.08.2017

Если вы откроете файл с помощью File :: BOM, он удалит спецификацию для ты.

use File::BOM;

open_bom(my $fh, $path, ':utf8')
person Pierre    schedule 24.06.2014

В идеале дескриптор файла должен делать это автоматически. Но если вы не в идеальной ситуации, это сработало для меня:

use Encode;

my $value = decode('UTF-8', $originalvalue);
$value =~ s/\N{U+FEFF}//;
person HoldOffHunger    schedule 30.09.2016