Come posso identificare uno strano personaggio?


10

Sto cercando di identificare uno strano personaggio che ho trovato in un file con cui sto lavorando:

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

Il file utilizza la codifica ISO-8859 e non può essere convertito in 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

La mia domanda principale è come posso interpretare l'output di odqui? Sto cercando di usare questa pagina che mi permette di tradurre tra diverse rappresentazioni di caratteri, ma mi dice che 005353come un "punto di codice esadecimale" è che non sembra giusto e 0aebcome un "punto di codice esadecimale" che, ancora, sembra sbagliato .

Così, come posso utilizzare una qualsiasi delle tre opzioni ( 355, 005353o 0aeb) per scoprire quale personaggio che dovrebbero rappresentare?

E sì, ho provato con gli strumenti Unicode ma non sembra nemmeno essere un carattere UTF valido:

$ 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 capisco la descrizione del personaggio Unicode U + FFFD, non è affatto un personaggio reale ma un segnaposto per un personaggio corrotto. Il che ha senso dato che il file non è in realtà codificato UTF-8.


5
EB potrebbe essere δ nella tabella codici 437 , oppure Ù nella tabella codici 850 , oppure ë in 8859-1 ; qualcuno di questi avrebbe senso? (si iconvlamenta perché non hai specificato il set di caratteri di origine, quindi utilizza il tuo valore predefinito che è probabilmente UTF-8.)
Stephen Kitt,

@StephenKitt sì, ëè quello che vedo quando i dati vengono utilizzati su un altro programma! Ma come posso saperlo? Non è da qualche parte nei dati che fornisco? Come l'hai trovato? Oh Avevo provato iconvcon -f ISO-8859ma lamentato conversion from ISO-8859' non è che beneficiano del sostegno.
terdon

1
Argh! Vedo, avevo bisogno di usare solo ebe ignorare l' 0xindicatore esadecimale o qualunque cosa sia. La mia ignoranza di questo genere di cose è profonda. Potresti pubblicare una risposta spiegando che @StephenKitt?
terdon

5
Il tuo errore cruciale qui è che ISO-8859 non è il nome di una codifica. È una famiglia di codifiche; a quanto pare, quello che stai cercando è ISO-8859-1.
tripleee,

1
Allora il tuo iconvsarebbe riuscito; e / o avresti potuto cercarlo, ad esempio su Wikipedia. Per questa codifica molto specifica, fileformat.info/info/unicode/char/00eb/index.htm funziona anche (Unicode è equivalente a ISO-8859-1 nell'intervallo 128-255, anche se ovviamente nessuna codifica UTF è compatibile con essa ).
tripleee,

Risposte:


22

Il file contiene due byte, EB e 0A in esadecimale. È probabile che il file utilizzi un set di caratteri con un byte per carattere, come ISO-8859-1 ; in quel set di caratteri, EB è ë:

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

Altri candidati sarebbero δ nella tabella codici 437 , Ù nella pagina codici 850 ...

od -xL'output è confuso in questo caso a causa dell'endianness; un'opzione migliore è -t x1che utilizza singoli byte:

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

od -xmappe a od -t x2cui legge due byte alla volta e su sistemi little-endian restituiscono i byte in ordine inverso.

Quando ti imbatti in un file come questo, che non è valido UTF-8 (o non ha senso se interpretato come un file UTF-8), non c'è modo infallibile per determinare automaticamente la sua codifica (e set di caratteri). Il contesto può aiutare: se è un file prodotto su un PC occidentale negli ultimi due decenni, c'è una buona probabilità che sia codificato in ISO-8859-1, -15 (la variante Euro) o Windows-1252; se è più vecchio di così, CP-437 e CP-850 sono probabilmente candidati. I file dei sistemi dell'Europa orientale, o dei sistemi russi o asiatici, utilizzerebbero diversi set di caratteri di cui non so molto. Poi c'è EBCDIC ... iconv -lelencherà tutti i set di caratteri che iconvconosce, e puoi procedere con prove ed errori da lì.

(A un certo punto conoscevo la maggior parte di CP-437 e ATASCII a memoria, erano i giorni.)


1
OK, nella pagina di Wikipedia a cui ti colleghi, posso vedere che ëè descritto come 00EBe 234. Cosa sono quelli extra 00? E perché non è 355come mi aspettavo oddall'output? Sto cercando di ottenere una risposta più generale su come posso usare l' odoutput per identificare il personaggio. Potresti forse spiegare qualcosa sull'interpretazione di codici esadecimali e / o quali informazioni sono necessarie per identificare un carattere sconosciuto (codifica e quant'altro)?
terdon

EB è 353 in ottale (non 355). Proverò a generalizzare ...
Stephen Kitt,

Spiacenti, intendevo 353. Quindi il 353 è una rappresentazione ottale, non decimale. Argh.
terdon

1
Sì, la "o" odsta per ottale ;-).
Stephen Kitt,

1
In ogni caso, (U + FFFD) verrebbe visualizzato dall'emulatore di terminale come sostituto di quel byte 0xeb che non forma un carattere valido in UTF-8. Non è chiaro il motivo per cui uniprops $(cat file)(virgolette mancanti tra l'altro) lo segnalerebbero (non conosco quel unipropscomando). unicode "$(cat file)"su Debian esce Sequence '\xeb' is not valid in charset 'UTF-8'come mi aspettavo.
Stéphane Chazelas,

5

Nota che odè l'abbreviazione di dump ottale , così 005353come i due byte come parola ottale, od -xè 0aebin esadecimale come parola, e il contenuto effettivo del tuo file sono i due byte ebe 0ain esadecimale, in questo ordine.

Quindi entrambi 005353e 0aebnon possono essere semplicemente interpretati come "punto di codice esadecimale".

0aè un feed di riga (LF) e ebdipende dalla codifica. filesta solo indovinando la codifica, potrebbe essere qualsiasi cosa. Senza ulteriori informazioni da dove proviene il file ecc., Sarà difficile scoprirlo.


Capisco che ciò è dovuto al fatto che non capisco come funzionano i punti di codice (o esadecimali), ma come posso saperlo? Di solito lo uso od -cperché produce output che posso capire. Come avrei potuto usare quello 355che produce per identificare il personaggio? E perché sta stampando 0aebanziché eb0ase 0aè la nuova riga?
terdon

@terdon endianness ... Vedi la mia risposta aggiornata.
Stephen Kitt,

2

È impossibile indovinare con precisione al 100% il set di caratteri dei file di testo.

Strumenti come chardet , firefox , file -i quando non sono definite informazioni esplicite sul set di caratteri (ad es. Se un HTML contiene un meta charset = ... nella testa, le cose sono più facili) proveranno ad usare euristiche che non sono così male se il testo è abbastanza grande.

Di seguito, dimostrerò il rilevamento dei set di caratteri con chardet( pip install chardet/ apt-get install python-chardetse necessario).

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

Dopo avere una buona charset candidato, siamo in grado di utilizzare iconv, recodeo simile a modificare il file charset al vostro charset "attivo" (nel mio caso utf-8) e vedere se indovinato ...

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

Alcuni set di caratteri (come iso-8859-3, iso-8859-1) hanno molti caratteri in comune - a volte non è facile vedere se abbiamo trovato il set di caratteri perfetto ...

Quindi è molto importante avere metadati associati al testo pertinente (ad es. XML).


Hmm. Non riesco a riprodurlo qui, si blocca e basta. Ma in ogni caso, non mi sta semplicemente dicendo la codifica del file? Il mio problema è identificare il carattere e non la codifica del file. Che già sapevo.
terdon

1
Spiacente, non sono riuscito a capire la domanda (il mio solito problema è identificare il set di caratteri). se ora la codifica, iconv -f ... -t utf-8 ti mostrerà i caratteri?
JJoao,

No. Mostro la codifica proprio lì. C'era un personaggio particolare non supportato da quella codifica ed è quel personaggio che stavo cercando di identificare.
terdon

1
Iso-8859 non è la codifica! la codifica è iso-8850-1. iso-8859 è uno standard iso che include diverse definizioni di chaset. Provafile -i ...
JJoao,

1
@terdon, mi dispiace insistere, ma, tutti i trucchi che hai provato a lavorare con il set di caratteri giusto. Es .: iconv -f ISO-8859-1 -t UTF-8 file
JJoao,

0
#!/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 ottengo un file che contiene, per esempio, la parola Begrung, posso dedurre che Begrüßung potrebbe essere inteso. Quindi lo converto da tutti gli encodindg noti e guardo, se ne viene trovato uno, che lo converte correttamente.

Di solito, ci sono più codifiche che sembrano adattarsi.

Per file più lunghi, potresti tagliare uno snippet invece di convertire centinaia di pagine.

Quindi lo chiamerei

encodingfinder.sh FILE Begrüßung

e gli script test, sia convertendolo con le codifiche conosciute, che producono "Begrüßung".

Per trovare tali personaggi, di solito è meno utile, poiché spesso i personaggi funky si distinguono. Dal contesto, la parola giusta da cercare di solito può essere dedotta. Ma non vogliamo verificare con un hexeditor, che cos'è questo byte, e quindi visitare infinite tabelle di codifiche, per trovare il nostro colpevole. :)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.