Кодировка HTML::Entities и один амперсанд

Я пытаюсь использовать следующую строку perl, как описано здесь: Кто-нибудь знает о плагине или сценарии vim для преобразования специальных символов в соответствующие объекты HTML? - для кодирования объектов HTML в Vim.

%!perl -p -i -e 'BEGIN { use HTML::Entities; use Encode; } $_=Encode::decode_utf8($_) unless Encode::is_utf8($_);  $_=Encode::encode("ascii", $_, sub{HTML::Entities::encode_entities(chr shift)});'

Он отлично работает (от £ до £, фигурные кавычки и т. д.), за исключением собственного амперсанда - & -, который остается как есть.

Я попытался удалить декодирование uf8 и просмотрел документацию CPAN для HTML::Entities.

Ответ:

@ZyX ответил на первоначальный вопрос, но, как отметили другие в комментариях, это избыточно, поскольку на самом деле нет необходимости использовать объекты HTML, если вы обслуживаете страницы с набором символов UTF-8 (что я и делаю, как с метатег -

<meta charset="utf-8">

а также в конфигурации Apache:

AddDefaultCharset utf-8

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

Очень важно убедиться, что любой редактор(ы), который вы используете для создания файлов, также записывает их в UTF-8.


person William Turrell    schedule 21.05.2011    source источник
comment
Из любопытства, почему вы делаете это в первую очередь?   -  person Pekka    schedule 21.05.2011
comment
Я изучаю Vim - часто приходится преобразовывать документы Word и другие источники с умными кавычками, апострофами, валютами и т. д. в правильно отформатированный HTML. Потратил некоторое время на поиск плагинов Vim - не было особого консенсуса по ним, и мне понравился подход Perl, который кто-то предложил, поскольку он (а) был довольно коротким, (б) использовал HTML::Entities, а не заново изобретал колесо, что, кажется, многие люди пытались сделать..   -  person William Turrell    schedule 21.05.2011
comment
Ах, достаточно справедливо. (В 90% случаев люди используют сущности для решения проблем с кодировкой, и в этом случае мой стандартный ответ — исправить проблему с кодировкой, отсюда и мой вопрос.) Проблема в том, что в HTML амперсанд является escape-символом для сущностей. . Таким образом, каждый настоящий амперсанд должен быть экранирован как &amp;. Не уверен, что лучший способ исправить это в этом случае, я не знаком с этими инструментами.   -  person Pekka    schedule 21.05.2011
comment
Ок, понял - спасибо.   -  person William Turrell    schedule 21.05.2011
comment
@Pekka: я думаю, что это входит в 90% всех случаев! Умные кавычки, апострофы, валюты и т. п. абсолютно являются правильно отформатированным HTML-кодом, дословно включенным в документ UTF-8, и не должны кодироваться сущностями, если только в этом нет особой необходимости — обычно для взаимодействия с редакторами, которые этого не делают. t grok Unicode, которых, к счастью, исчезающе мало.   -  person bobince    schedule 21.05.2011
comment
@bobince полезно знать - я не совсем понимаю, какие наборы символов могут присутствовать в документе Word. В этом случае @williamt возникает вопрос, нужно ли вообще то, что вы хотите сделать :)   -  person Pekka    schedule 21.05.2011
comment
@bobince @Pekka Спасибо - до сегодняшнего дня я полностью упускал из виду, что указание UTF-8 вообще устранило необходимость в объектах HTML - это то, чему я научился много лет назад и с тех пор слепо упорствовал. Теперь я знаю, что это сэкономит мне много времени...   -  person William Turrell    schedule 21.05.2011
comment
@williamt: использование set fileencoding в vimrc бессмысленно: его значение будет перезаписано после чтения файла. Вы должны установить «fileencodings» в правильное значение (или установить его в пустую строку, если вы хотите, чтобы настройка «fileencoding» в vimrc действовала).   -  person ZyX    schedule 21.05.2011
comment
@Zyx Спасибо. Я удалил эту строку — она казалась слишком запутанной, учитывая, что в Vim есть переменные «кодирование», «кодирование файлов» и «кодирование файлов». Кажется достаточно безопасным полагаться на правильную настройку «локали» и гарантировать, что вы корректируете веб-страницы с указанной «мета-кодировкой» (но опять же, поправьте меня, если я ошибаюсь..)   -  person William Turrell    schedule 21.05.2011
comment
@williamt Кодировка в мета не имеет никакого эффекта, если у вас нет плагина, который повторно открывает файл, если кодировка, указанная в мета, не соответствует кодировке файла (на самом деле она используется только для записи, но я не знаю, как использовать кодировку для чтение файла. 'fileencoding' сначала устанавливается при чтении файла в кодировку, используемую для чтения, но может быть перезаписана позже).   -  person ZyX    schedule 21.05.2011


Ответы (2)


Мой ответ заключался только в кодировании символов, которые находятся выше диапазона ascii. Если вы хотите что-то закодировать как html, вы должны использовать

$text=HTML::Entities::encode_entities($text);

:

%!perl -MHTML::Entities -MEncode -p -i -e '$_=Encode::decode_utf8($_) unless Encode::is_utf8($_); $_=HTML::Entities::encode_entities($_);'

Я не использовал это в этом ответе, потому что TS запросил только кодирование символов Юникода без кодирования <, >, &.

Кстати, вы можете использовать $text=HTML::Entities::encode_entities($text, '<>&"'); для кодирования только действительно небезопасных символов (хотя я думаю, это легко выразить с помощью vimscript:

:let entities={'<': 'lt', '>': 'gt', '&': 'amp', '"': 'quot'}
:execute '%s/['.escape(join(keys(entities), ''), '\-]^').']/\="&".entities[submatch(0)].";"/g'
person ZyX    schedule 21.05.2011
comment
Я хочу повторить рекомендацию кодировать только действительно небезопасные символы. - person Anirvan; 11.06.2011

perl -MHTML::Entities -i -e 'print encode_entities shift'

должно работать, не так ли?

person i-blis    schedule 21.05.2011
comment
Нет. Во-первых, угадайте, почему я использовал Encode::decode_utf8? Во-вторых, вы работаете со следующим аргументом perl, в то время как вам нужно работать с заданными файлами или стандартным выводом. - person ZyX; 21.05.2011
comment
Что ж, я воспринял вашу команду -i как должное и как необходимое для вашего Vim. Во-вторых, он отлично работает, когда я передаю данные из файла с параметром -n. Я имею в виду, что ваша проблема была с &, не так ли. я получаю - person i-blis; 21.05.2011
comment
@i-blis 1. Мне не удалось получить никаких результатов, запустив echo '&' | perl -MHTML::Entities -i -e 'print encode_entities shift', хотя я могу получить их, запустив perl -MHTML::Entities -i -e 'print encode_entities shift' '&'. 2. Это была не моя проблема. 3. Попробуйте таким образом закодировать любой многобайтовый символ юникода и посмотрите, что получится (может быть, это зависит от версии perl, я что-то слышал об изменениях юникода в самых последних версиях perl). - person ZyX; 21.05.2011
comment
@ZyX 1. Я знаю поведение с -i, спасибо. Я предоставил oneliner в той же форме, что и в вопросе. 2. Извините за это. 3. По-видимому, нет проблем с кодировкой многобайтовых символов юникода (без явного декодирования) с помощью Perl 5.12 (я тестировал с кодировкой UTF-8 на русском языке). - person i-blis; 21.05.2011
comment
@i-blis 3. Вы уверены? perl -MHTML::Entities -i -e 'print encode_entities shift' '«»' приводит к &Acirc;&laquo;&Acirc;&raquo;, а &Acirc; не должно быть. Если добавить -MEncode и decode_utf8 все нормально. Я предполагаю, что у вас есть локаль, отличная от юникода: когда я использую LANG=ru_RU.CP1251 perl -MHTML::Entities -i -e 'print encode_entities shift' $(echo «» | iconv -f utf-8 -t cp1251), он дает результат, как и ожидалось (мне действительно нужно было использовать use open qw(:locale) вместо декодирования utf8, но я не знал о локалях, отличных от юникода). - person ZyX; 21.05.2011
comment
@ZyX, я даже не знал, что на консоли, на которой я тестировал, локаль была установлена ​​​​на ru_RU.KOI8-R. Я сошел с ума, когда не смог воспроизвести его на своей машине (en_GB.UTF-8). Так что да, кодирование многобайтового юникода требует декодирования. Мои извинения за неудачный тест. - person i-blis; 21.05.2011