Como posso identificar um personagem estranho?

Como posso identificar um personagem estranho?

Estou tentando identificar um caractere estranho que encontrei em um arquivo com o qual estou trabalhando:

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

O arquivo usa codificação ISO-8859 e não pode ser convertido para 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

Minha principal questão é como posso interpretar a saída daqui od? estou tentando usaresta páginao que me permite traduzir entre diferentes representações de caracteres, mas me diz que 005353como um "ponto de código hexadecimal" é o que não parece certo e 0aebcomo um "ponto de código hexadecimal" é o que, novamente, parece errado.

Então, como posso usar qualquer uma das três opções ( 355, 005353ou 0aeb) para descobrir qual caractere elas deveriam representar?

E sim, tentei com ferramentas Unicode, mas também não parece ser um caractere UTF válido:

$ 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

se bem entendi a descrição do caractere Unicode U + FFFD, ele não é um caractere real, mas um espaço reservado para um caractere corrompido. O que faz sentido, já que o arquivo não é realmente codificado em UTF-8.

Responder1

Seu arquivo contém dois bytes, EB e 0A em hexadecimal. É provável que o arquivo esteja usando um conjunto de caracteres com um byte por caractere, comoISO-8859-1; nesse conjunto de caracteres, EB é ë:

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

Outros candidatos seriam δ empágina de código 437, Ù empágina de código 850...

od -xa saída de é confusa neste caso por causa do endianismo; uma opção melhor é -t x1usar bytes únicos:

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

od -xmapeia para od -t x2o qual lê dois bytes por vez e, em sistemas little-endian, gera os bytes na ordem inversa.

Quando você se depara com um arquivo como este, que não é UTF-8 válido (ou não faz sentido quando interpretado como um arquivo UTF-8), não há uma maneira infalível de determinar automaticamente sua codificação (e conjunto de caracteres). O contexto pode ajudar: se for um arquivo produzido em um PC ocidental nas últimas décadas, há uma boa chance de que esteja codificado em ISO-8859-1, -15 (a variante Euro) ou Windows-1252; se for mais antigo, CP-437 e CP-850 são prováveis ​​candidatos. Arquivos de sistemas do Leste Europeu, ou sistemas russos, ou sistemas asiáticos, usariam diferentes conjuntos de caracteres sobre os quais não sei muito. Depois, há o EBCDIC... iconv -llistará todos os conjuntos de caracteres que iconvvocê conhece e você poderá prosseguir por tentativa e erro a partir daí.

(A certa altura eu sabia de cor a maior parte do CP-437 e ATASCII, eram os dias.)

Responder2

Observe que odé uma abreviação dedespejo octal, assim 005353como os dois bytes como palavra octal, od -xestá 0aebem hexadecimal como palavra, e o conteúdo real do seu arquivo são os dois bytes ebe 0aem hexadecimal, nesta ordem.

Portanto, ambos 005353e 0aebnão podem ser interpretados apenas como "ponto de código hexadecimal".

0aé um feed de linha (LF) e ebdepende da sua codificação. fileestá apenas adivinhando a codificação, pode ser qualquer coisa. Sem mais informações de onde veio o arquivo, etc., será difícil descobrir.

Responder3

É impossível adivinhar com 100% de precisão o conjunto de caracteres dos arquivos de texto.

Ferramentas comocharete,Raposa de fogo,arquivo -euquando não há informações explícitas de charset definidas (por exemplo, se um HTML contém um meta charset=... no cabeçalho, as coisas são mais fáceis) tentará usar heurísticas que não sejam tão ruins se o texto for grande o suficiente.

A seguir, demonstro a detecção de charset com chardet( pip install chardet/ apt-get install python-chardetse necessário).

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

Depois de ter um bom candidato a charset, podemos usar iconv, recodeou similar para alterar o charset do arquivo para o seu charset "ativo" (no meu caso utf-8) e ver se acertou...

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

Alguns conjuntos de caracteres (como iso-8859-3, iso-8859-1) têm muitos caracteres em comum - às vezes não é fácil ver se encontramos o conjunto de caracteres perfeito...

Por isso é muito importante ter metadados associados a textos relevantes (por exemplo, XML).

Responder4

#!/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 

Se eu obtiver um arquivo que contenha, por exemplo, a palavra Begrung, posso inferir que Begrüßung pode ser o significado. Então eu o converto por todas as codificações conhecidas e procuro se alguma foi encontrada, o que a converte corretamente.

Normalmente, existem várias codificações que parecem se encaixar.

Para arquivos mais longos, você pode cortar um trecho em vez de converter centenas de páginas.

Então eu chamaria isso

encodingfinder.sh FILE Begrüßung

e o script testa, seja convertendo-o com as codificações conhecidas, quais delas produzem "Begrüßung".

Para encontrar esses personagens, menos geralmente ajuda, já que personagens descolados geralmente se destacam. A partir do contexto, geralmente é possível inferir a palavra certa a ser pesquisada. Mas não queremos verificar com um editor hexadecimal que byte é esse e depois visitar infinitas tabelas de codificações para encontrar nosso agressor. :)

informação relacionada