¿Cómo puedo identificar un personaje extraño?

¿Cómo puedo identificar un personaje extraño?

Estoy tratando de identificar un carácter extraño que encontré en un archivo con el que estoy trabajando:

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

El archivo utiliza codificación ISO-8859 y no se puede convertir a 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

Mi pregunta principal es ¿cómo puedo interpretar el resultado de odaquí? estoy tratando de usaresta páginalo que me permite traducir entre diferentes representaciones de caracteres, pero me dice que 005353como "punto de código hexadecimal" es lo que no parece correcto y 0aebcomo "punto de código hexadecimal" es lo que, nuevamente, parece incorrecto.

Entonces, ¿cómo puedo usar cualquiera de las tres opciones ( 355, 005353o 0aeb) para saber qué personaje se supone que representan?

Y sí, lo intenté con las herramientas Unicode pero tampoco parece ser un carácter 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

Si entiendo la descripción del carácter Unicode U+FFFD, no es un carácter real sino un marcador de posición para un carácter corrupto. Lo cual tiene sentido ya que el archivo en realidad no está codificado en UTF-8.

Respuesta1

Su archivo contiene dos bytes, EB y 0A en hexadecimal. Es probable que el archivo esté usando un juego de caracteres con un byte por carácter, comoISO-8859-1; en ese conjunto de caracteres, EB es ë:

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

Otros candidatos serían δ enpágina de códigos 437, Ù enpágina de códigos 850...

od -xLa salida de es confusa en este caso debido a la endianidad; una mejor opción es -t x1la que utiliza bytes únicos:

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

od -xmapas en od -t x2los que lee dos bytes a la vez y, en sistemas little-endian, genera los bytes en orden inverso.

Cuando te encuentras con un archivo como este, que no es UTF-8 válido (o no tiene sentido cuando se interpreta como un archivo UTF-8), no existe una forma infalible de determinar automáticamente su codificación (y conjunto de caracteres). El contexto puede ayudar: si se trata de un archivo producido en una PC occidental en las últimas dos décadas, es muy probable que esté codificado en ISO-8859-1, -15 (la variante europea) o Windows-1252; si es más antiguo, CP-437 y CP-850 son candidatos probables. Los archivos de sistemas de Europa del Este, de sistemas rusos o de sistemas asiáticos usarían diferentes conjuntos de caracteres de los que no sé mucho. Luego está EBCDIC... iconv -lenumerará todos los conjuntos de caracteres que iconvconoce y podrá proceder mediante prueba y error desde allí.

(En un momento me sabía de memoria la mayor parte de CP-437 y ATASCII, esos eran los días).

Respuesta2

Tenga en cuenta que odes la abreviatura devolcado octal, también lo 005353son los dos bytes como palabra octal, od -xestá 0aeben hexadecimal como palabra, y el contenido real de su archivo son los dos bytes eby 0aen hexadecimal, en este orden.

Por lo tanto, ambos 005353y 0aebno pueden interpretarse simplemente como "puntos de código hexadecimal".

0aes un avance de línea (LF) y ebdepende de su codificación. fileEs solo adivinar la codificación, podría ser cualquier cosa. Sin más información de dónde proviene el archivo, etc., será difícil averiguarlo.

Respuesta3

Es imposible adivinar con un 100% de precisión el juego de caracteres de los archivos de texto.

Herramientas comochardet,firefox,archivo -yocuando no hay información explícita del juego de caracteres definida (por ejemplo, si un HTML contiene un meta juego de caracteres=... en el encabezado, las cosas son más fáciles) intentará usar heurísticas que no son tan malas si el texto es lo suficientemente grande.

A continuación, demuestro la detección de juegos de caracteres con chardet( pip install chardet/ apt-get install python-chardetsi es necesario).

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

Después de tener un buen conjunto de caracteres candidato, podemos usar iconv, recodeo similar, para cambiar el conjunto de caracteres del archivo a su conjunto de caracteres "activo" (en mi caso, utf-8) y ver si adivinó correctamente...

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

Algunos conjuntos de caracteres (como iso-8859-3, iso-8859-1) tienen muchos caracteres en común; a veces no es fácil ver si encontramos el conjunto de caracteres perfecto...

Por eso es muy importante tener metadatos asociados con el texto relevante (por ejemplo, XML).

Respuesta4

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

Si obtengo un archivo que contiene, por ejemplo, la palabra Begrung, puedo inferir que podría referirse a Begrüßung. Así que lo convierto con todas las codificaciones conocidas y miro si se encuentra alguna que lo convierta correctamente.

Por lo general, existen múltiples codificaciones que parecen encajar.

Para archivos más largos, puedes cortar un fragmento en lugar de convertir cientos de páginas.

Entonces yo lo llamaría

encodingfinder.sh FILE Begrüßung

y el script prueba, mediante conversión con las codificaciones conocidas, cuál de ellas produce "Begrüßung".

Para encontrar tales personajes, normalmente menos ayuda, ya que los personajes originales a menudo destacan. A partir del contexto, normalmente se puede inferir la palabra correcta a buscar. Pero no queremos comprobar con un editor hexadecimal qué byte es este y luego visitar infinitas tablas de codificaciones para encontrar a nuestro infractor. :)

información relacionada