Как распознать странного персонажа?

Как распознать странного персонажа?

Я пытаюсь идентифицировать странный символ, который я нашел в файле, с которым работаю:

$ cat file
$ od file
0000000 005353
0000002
$ od -c file
0000000 353  \n
0000002
$ od -x file
0000000 0aeb
0000002

Файл использует кодировку ISO-8859 и не может быть преобразован в UTF-8:

$ iconv -f ISO-8859 -t UTF-8 file
iconv: conversion from `ISO-8859' is not supported
Try `iconv --help' or `iconv --usage' for more information.
$ iconv  -t UTF-8 file
iconv: illegal input sequence at position 0
$ file file
file: ISO-8859 text

Мой главный вопрос в том, как я могу интерпретировать вывод odздесь? Я пытаюсь использоватьэта страницачто позволяет мне выполнять перевод между различными представлениями символов, но сообщает мне, что 005353«шестнадцатеричный код» — это, что не кажется правильным, а 0aeb«шестнадцатеричный код» — это, что, опять же, кажется неправильным.

Итак, как я могу использовать любой из трех вариантов ( 355, 005353или 0aeb), чтобы узнать, какой символ они должны представлять?

И да, я пробовал использовать инструменты Unicode, но, похоже, это тоже недопустимый символ UTF:

$ uniprops $(cat file)
U+FFFD ‹�› \N{REPLACEMENT CHARACTER}
    \pS \p{So}
    All Any Assigned Common Zyyy So S Gr_Base Grapheme_Base Graph X_POSIX_Graph
       GrBase Other_Symbol Print X_POSIX_Print Symbol Specials Unicode

Если я правильно понял описание символа Unicode U+FFFD, то это вообще не настоящий символ, а заполнитель для поврежденного символа. Что имеет смысл, поскольку файл на самом деле не закодирован в UTF-8.

решение1

Ваш файл содержит два байта, EB и 0A в шестнадцатеричном формате. Вероятно, файл использует набор символов с одним байтом на символ, напримерИСО-8859-1; в этом наборе символов EB — это ë:

$ printf "\353\n" | iconv -f ISO-8859-1
ë

Другие кандидаты будут δ вкод страницы 437, Ù вкод страницы 850...

od -xВывод в этом случае сбивает с толку из-за порядка байтов; лучшим вариантом является -t x1вариант, использующий отдельные байты:

$ printf "\353\n" | od -t x1
0000000 eb 0a
0000002

od -xкарты, на od -t x2которые считываются два байта за раз, а в системах с прямым порядком байтов выводятся байты в обратном порядке.

Когда вы сталкиваетесь с таким файлом, который не является допустимым UTF-8 (или не имеет смысла при интерпретации как файл UTF-8), нет надежного способа автоматически определить его кодировку (и набор символов). Контекст может помочь: если это файл, созданный на западном ПК в последние пару десятилетий, есть большая вероятность, что он закодирован в ISO-8859-1, -15 (европейский вариант) или Windows-1252; если он старше, то вероятными кандидатами являются CP-437 и CP-850. Файлы из восточноевропейских систем, или российских систем, или азиатских систем будут использовать другие наборы символов, о которых я не очень много знаю. Затем есть EBCDIC..., который iconv -lперечислит все наборы символов, о которых iconvзнает, и вы можете продолжить методом проб и ошибок оттуда.

(В какой-то момент я знал большую часть CP-437 и ATASCII наизусть, вот это были времена.)

решение2

Обратите внимание, что odэто сокращение отвосьмеричный дамп, поэтому 005353два байта представлены в восьмеричном формате как слово, od -xв 0aebшестнадцатеричном формате как слово, и фактическое содержимое вашего файла — это два байта ebи 0aв шестнадцатеричном формате, в этом порядке.

Поэтому и то, 005353и 0aebдругое нельзя интерпретировать просто как «шестнадцатеричный код».

0aэто перевод строки (LF), и ebзависит от вашей кодировки. fileэто просто предположение о кодировке, это может быть что угодно. Без какой-либо дополнительной информации, откуда взялся файл и т. д., будет сложно выяснить.

решение3

Невозможно со 100% точностью угадать кодировку текстовых файлов.

Такие инструменты, какшарде,Fire Fox,файл -iкогда явно не определена информация о наборе символов (например, если HTML содержит meta charset=... в заголовке, все проще), попытается использовать эвристики, которые не так уж плохи, если текст достаточно большой.

Далее я продемонстрирую определение кодировки с помощью chardet( pip install chardet/ apt-get install python-chardetпри необходимости).

$ echo "in Noël" | iconv -f utf8 -t latin1  | chardet
<stdin>: windows-1252 with confidence 0.73

После того, как у нас есть подходящий вариант набора символов, мы можем использовать iconv, recodeили что-то подобное, чтобы изменить набор символов файла на ваш «активный» набор символов (в моем случае utf-8) и посмотреть, правильно ли он угадал...

iconv -f windows-1252  -t utf-8 file

Некоторые наборы символов (например, iso-8859-3, iso-8859-1) имеют много общих символов — иногда нелегко понять, нашли ли мы идеальный набор символов...

Поэтому очень важно иметь метаданные, связанные с соответствующим текстом (например, XML).

решение4

#!/bin/bash
#
# Search in a file, a known (part of a ) String (i.E.: Begrüßung),
# by testing all encodings
#
[[ $# -ne 2 ]] && echo "Usage: encoding-finder.sh FILE fUnKy_CHAR_FOR_SURE_IN_FILE" && exit
FILE=$1
PATTERN=$2
for enc in $( iconv -l | sed 's/..$//') 
do 
    iconv -f $enc -t UTF-8 $FILE  2>/dev/null | grep -m 1 $PATTERN && echo $enc 
done 

Если я получаю файл, содержащий, например, слово Begrung, я могу сделать вывод, что, возможно, имеется в виду Begrüßung. Поэтому я конвертирую его всеми известными кодировками и смотрю, найдется ли та, которая конвертирует его правильно.

Обычно существует несколько кодировок, которые кажутся подходящими.

Для более длинных файлов вы можете вырезать фрагмент вместо того, чтобы конвертировать сотни страниц.

Так что я бы назвал это

encodingfinder.sh FILE Begrüßung

и скрипт проверяет, конвертируя его с известными кодировками, какие из них производят «Begrüßung».

Чтобы найти такие символы, less обычно помогает, так как странные символы часто выделяются. Из контекста обычно можно вывести правильное слово для поиска. Но мы не хотим проверять с помощью шестнадцатеричного редактора, какой это байт, а затем посещать бесконечные таблицы кодировок, чтобы найти нашего нарушителя. :)

Связанный контент