Вопрос или проблема
Мои входные данные следующие (как сгенерировано командой hexdump):
000000f0 69 61 6e e2 80 99 73 20 65 79 65 73 20 61 62 72 |ian...s eyes abr|
Когда я открываю этот html () файл в Firefox, он отображает эти символы как:
ian’s eyes abr
Согласно ссылке https://superuser.com/questions/1237545/characters-in-email-displayed-like-e2-80-99, “E2 80 99 это последовательность шестнадцатеричных значений, кодирующих правую апостроф (’) в UTF-8”.
Этот сайт подтверждает: https://www.utf8-chartable.de/unicode-utf8-table.pl?start=8192&number=128
Когда я запускаю эту команду iconv на файле, содержащем эти символы:
iconv -f UTF-8 -t ISO-8859-15 test_chapter.html > blah.html
Я получаю вывод:
iconv: illegal input sequence at position 243
и содержимое “blah.html” обрывается точно там, где должен быть апостроф.
Итак, подведем итог, интернет говорит, что это допустимая последовательность байтов для UTF-8, но iconv не согласен.
Кто-нибудь может помочь мне понять, что происходит? Это баг в iconv?
Кстати, когда я использую этот html файл с kindlegen для создания файла AZW, символ отображается неправильно. Весь интернет говорит мне, что мне нужно сконвертировать файл в UTF-8, но, насколько я могу судить, он уже в этом формате!
Ваш комментарий:
возможно, проблема в конвертации в ISO-8859-15, а не в конвертации из UTF-8
на правильном пути. Проблема в том, что в ISO-8859-15 нет символа ’
. Наиболее похожий символ '
. См. что говорит man 1 iconv
в Debian 12, который я использую:
Если строка
//TRANSLIT
добавляется к to-encoding, символы, которые конвертируются, подвергаются транслитерации при необходимости и если это возможно. Это означает, что когда символ не может быть представлен в целевой кодировке, он может быть заменен на один или несколько похожих символов. Символы, находящиеся вне целевой кодировки и которые нельзя транслитерировать, заменяются на знак вопроса (?
) в выходных данных.
Используйте -t ISO-8859-15//TRANSLIT
тогда.
В качестве доказательства концепции, это работает для меня (в локали pl_PL.UTF-8
):
printf '%s\n' 'ian’s eyes abr' | iconv -f UTF-8 -t ISO-8859-15//TRANSLIT
Вывод ian's eyes abr
(с новой строкой в конце). Так получилось, что представление этой конкретной строки идентично в ISO-8859-15 и в UTF-8, поэтому я решил не усложнять команду дополнительной передачей через iconv -f ISO-8859-15 -t UTF-8
.
.
Ответ или решение
Если вы сталкиваетесь с проблемой, когда iconv
не распознает корректный UTF-8 символ и выводит сообщение об ошибке, важно понимать, что проблема, скорее всего, связана с несовместимостью символьных наборов, а не с неверной интерпретацией UTF-8.
Контекст проблемы
Давайте посмотрим на ваш пример:
-
Исходные данные в hex:
69 61 6e e2 80 99 73 20 65 79 65 73 20 61 62 72
- Здесь
e2 80 99
— это кодировка символа правой одинарной кавычки (’), что подтверждается стандартами UTF-8.
- Здесь
-
Командная строка:
iconv -f UTF-8 -t ISO-8859-15 test_chapter.html > blah.html
- Вы получаете ошибку:
iconv: illegal input sequence at position 243
.
- Вы получаете ошибку:
Анализ проблемы
Причина ошибки заключается в том, что символ правая одинарная кавычка (’) присутствует в UTF-8, но его нет в ISO-8859-15, на который вы пытаетесь конвертировать.
Решение проблемы
Вы можете воспользоваться опцией //TRANSLIT
, чтобы приблизить символ к доступному в ISO-8859-15, заменив его на обычную одинарную кавычку (‘).
Пример команды:
iconv -f UTF-8 -t ISO-8859-15//TRANSLIT test_chapter.html > blah.html
Это позволит iconv
попытаться преобразовать отсутствующие в ISO-8859-15 символы в схожие, если это возможно.
Подводя итог
- Причина: Символ отсутствует в ISO-8859-15.
- Решение: Использование
//TRANSLIT
для замены на схожий символ. - Проверка: Убедитесь, что ваш HTML файл действительно в UTF-8, используя команду:
file -bi test_chapter.html
Заключение
Сделайте акцент на корректной кодировке ваших данных и учитывайте ограничения целевой кодировки при преобразованиях. Используйте //TRANSLIT
для обеспечения максимальной совместимости, если конечный набор символов этого требует.