Wie kann ich einen seltsamen Charakter identifizieren?

10

Ich versuche, ein seltsames Zeichen zu identifizieren, das ich in einer Datei gefunden habe, mit der ich arbeite:

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

Die Datei verwendet die ISO-8859-Codierung und kann nicht in UTF-8 konvertiert werden:

$ 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

Meine Hauptfrage ist, wie ich die Ausgabe von odhier interpretieren kann . Ich versuche, diese Seite zu verwenden, auf der ich zwischen verschiedenen Zeichendarstellungen übersetzen kann, aber sie sagt mir, dass 005353ein "Hex-Code-Punkt" nicht richtig und 0aebein "Hex-Code-Punkt" wiederum falsch erscheint .

Also, wie kann ich eine der drei Optionen verwenden ( 355, 005353oder 0aeb) , um herauszufinden , was Charakter , den sie darstellen soll?

Und ja, ich habe es mit Unicode-Tools versucht, aber es scheint auch kein gültiges UTF-Zeichen zu sein:

$ 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

Wenn ich die Beschreibung des Unicode U + FFFD-Zeichens verstehe, ist es überhaupt kein echtes Zeichen, sondern ein Platzhalter für ein beschädigtes Zeichen. Dies ist sinnvoll, da die Datei nicht UTF-8-codiert ist.

terdon
quelle
5
EB könnte δ in Codepage 437 oder Ù in Codepage 850 oder ë in 8859-1 sein ; Würde einer von denen Sinn machen? ( iconvbeschwert sich, weil Sie den Quellzeichensatz nicht angegeben haben, daher wird Ihr Standard verwendet, der wahrscheinlich UTF-8 ist.)
Stephen Kitt
@StephenKitt ja, ëdas sehe ich, wenn die Daten in einem anderen Programm verwendet werden! Aber wie kann ich das wissen? Ist es nicht irgendwo in den Daten, die ich zur Verfügung stelle? Wie hast du das gefunden? Oh, ich hatte es iconvmit versucht, -f ISO-8859aber es beschwerte sich über conversion from ISO-8859 "wird nicht unterstützt".
Terdon
1
Argh! Ich verstehe, ich musste nur ebden 0xHex-Indikator oder was auch immer das verwenden und ignorieren . Meine Unkenntnis dieser Art von Dingen ist tief. Könnten Sie eine Antwort posten, die erklärt, dass @StephenKitt?
Terdon
5
Ihr entscheidender Fehler hierbei ist, dass ISO-8859 nicht der Name einer Codierung ist. Es ist eine Familie von Kodierungen; Anscheinend suchen Sie nach ISO-8859-1.
Tripleee
1
Dann iconvwäre es dir gelungen; und / oder du hättest es zB bei Wikipedia nachschlagen können. Für diese sehr spezifische Codierung funktioniert auch fileformat.info/info/unicode/char/00eb/index.htm (Unicode entspricht ISO-8859-1 im Bereich von 128-255, obwohl natürlich keine UTF-Codierung damit kompatibel ist ).
Tripleee

Antworten:

22

Ihre Datei enthält zwei Bytes, EB und 0A in hex. Es ist wahrscheinlich, dass die Datei einen Zeichensatz mit einem Byte pro Zeichen verwendet, z. B. ISO-8859-1 . In diesem Zeichensatz ist EB ë:

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

Andere Kandidaten wären δ in Codepage 437 , Ù in Codepage 850 ...

od -xDie Ausgabe ist in diesem Fall wegen der Endianness verwirrend. Eine bessere Option ist -t x1die Verwendung einzelner Bytes:

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

od -xZuordnungen, zu od -t x2denen zwei Bytes gleichzeitig gelesen werden, und auf Little-Endian-Systemen werden die Bytes in umgekehrter Reihenfolge ausgegeben.

Wenn Sie auf eine solche Datei stoßen, die kein gültiges UTF-8 ist (oder bei der Interpretation als UTF-8-Datei keinen Sinn ergibt), gibt es keine narrensichere Möglichkeit, die Codierung (und den Zeichensatz) automatisch zu bestimmen. Der Kontext kann helfen: Wenn es sich um eine Datei handelt, die in den letzten Jahrzehnten auf einem westlichen PC erstellt wurde, besteht eine gute Chance, dass sie in ISO-8859-1, -15 (Euro-Variante) oder Windows-1252 codiert ist. Wenn es älter ist, sind CP-437 und CP-850 wahrscheinlich Kandidaten. Dateien aus osteuropäischen oder russischen oder asiatischen Systemen würden unterschiedliche Zeichensätze verwenden, über die ich nicht viel weiß. Dann gibt es EBCDIC ... iconv -llistet alle Zeichensätze auf, die Sie iconvkennen, und Sie können von dort aus durch Ausprobieren fortfahren.

(Irgendwann wusste ich, dass die meisten CP-437 und ATASCII auswendig konnten, das waren die Tage.)

Stephen Kitt
quelle
1
OK, auf der Wikipedia-Seite, auf die Sie verlinken, kann ich sehen, dass ëdies als 00EBund beschrieben wird 234. Was sind das extra 00? Und warum ist es nicht so, 355wie ich es von der odAusgabe erwartet habe ? Ich versuche eine allgemeinere Antwort darauf zu bekommen, wie ich die odAusgabe verwenden kann, um den Charakter zu identifizieren. Könnten Sie vielleicht etwas über die Interpretation von Hex-Codes erklären und / oder welche Informationen benötigt werden, um ein unbekanntes Zeichen identifizieren zu können (Codierung und was auch immer)?
Terdon
EB ist 353 in Oktal (nicht 355). Ich werde versuchen zu verallgemeinern ...
Stephen Kitt
Hoppla, tut mir leid, meinte ich 353. Der 353 ist also eine oktale Darstellung, keine Dezimalzahl. Argh.
Terdon
1
Ja, das "o" in odsteht für oktal ;-).
Stephen Kitt
1
In jedem Fall würde das (U + FFFD) vom Terminalemulator als Ersatz für das 0xeb-Byte angezeigt, das in UTF-8 kein gültiges Zeichen bildet. Es ist nicht klar, warum uniprops $(cat file)(übrigens fehlende Anführungszeichen) dies melden würden (ich weiß nichts über diesen unipropsBefehl). unicode "$(cat file)"auf Debian wird Sequence '\xeb' is not valid in charset 'UTF-8'wie erwartet ausgegeben .
Stéphane Chazelas
5

Beachten Sie, dass die odAbkürzung für ist Oktal - Dump , so 005353sind die beiden Bytes als Oktalwortes, od -xist 0aebin Hexadezimal als Wort, und die tatsächlichen Inhalte der Datei sind die beiden Bytes ebund 0ain hexadezimal, in dieser Reihenfolge.

Also beides 005353und 0aebkann nicht einfach als "Hex-Code-Punkt" interpretiert werden.

0aist ein Zeilenvorschub (LF) und ebhängt von Ihrer Codierung ab. fileerrät nur die Kodierung, es könnte alles sein. Ohne weitere Informationen, woher die Datei stammt usw. wird es schwierig sein, dies herauszufinden.

dirkt
quelle
Mir ist klar, dass ich nicht verstehe, wie Codepunkte (oder Hex, wirklich) funktionieren, aber wie kann ich das wissen? Ich benutze normalerweise, od -cda dies eine Ausgabe erzeugt, die ich verstehen kann. Wie hätte ich das verwenden können 355, um den Charakter zu identifizieren? Und warum wird gedruckt, 0aebanstatt eb0aob 0aes sich um die neue Zeile handelt?
Terdon
@terdon endianness ... Siehe meine aktualisierte Antwort.
Stephen Kitt
2

Es ist unmöglich, den Zeichensatz von Textdateien mit 100% iger Genauigkeit zu erraten.

Tools wie Chardet , Firefox , Datei -i, wenn keine expliziten Zeichensatzinformationen definiert sind (z. B. wenn ein HTML einen Meta-Zeichensatz enthält = ... im Kopf, sind die Dinge einfacher), versuchen, Heuristiken zu verwenden, die nicht so schlecht sind, wenn Der Text ist groß genug.

Im Folgenden demonstriere ich die Zeichensatzerkennung mit chardet( pip install chardet/ apt-get install python-chardetfalls erforderlich).

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

Nachdem Kandidaten gut charset, können wir verwenden iconv, recodeoder ähnlich , die Datei charset zu Ihrem „aktiv“ charset zu ändern (in meinem Fall utf-8) und sehen , ob es richtig geraten ...

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

Einige Zeichensätze (wie iso-8859-3, iso-8859-1) haben viele Zeichen gemeinsam - manchmal ist es nicht leicht zu erkennen, ob wir den perfekten Zeichensatz gefunden haben ...

Daher ist es sehr wichtig, Metadaten mit relevantem Text (z. B. XML) verknüpft zu haben.

JJoao
quelle
Hmm. Ich kann es hier nicht reproduzieren, es stürzt einfach ab. Aber sagt mir das nicht einfach die Kodierung der Datei? Mein Problem besteht darin, das Zeichen zu identifizieren , nicht die Codierung der Datei. Das wusste ich schon.
Terdon
1
Entschuldigung, ich habe die Frage nicht verstanden (mein übliches Problem ist die Identifizierung des Zeichensatzes). Wenn Sie jetzt die Codierung, iconv -f ... -t utf-8 werden Sie die Zeichen zeigen?
JJoao
Nein, ich zeige die Kodierung genau dort. Es gab ein bestimmtes Zeichen, das von dieser Codierung nicht unterstützt wurde, und es ist dieses Zeichen, das ich identifizieren wollte.
Terdon
1
Iso-8859 ist nicht die Kodierung! Die Kodierung ist iso-8850-1. iso-8859 ist ein iso-Standard, der mehrere Chaset-Definitionen enthält. Versuchen Siefile -i ...
JJoao
1
@terdon, tut mir leid, aber alle Tricks, die Sie ausprobiert haben, funktionieren mit dem richtigen Zeichensatz. Beispiel: 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 

Wenn ich eine Datei bekomme, die zum Beispiel das Wort Begrung enthält, kann ich daraus schließen, dass Begrüßung gemeint sein könnte. Also konvertiere ich es durch alle bekannten Codierungen und schaue, ob eine gefunden wird, die es richtig konvertiert.

Normalerweise gibt es mehrere Codierungen, die zu passen scheinen.

Bei längeren Dateien können Sie ein Snippet ausschneiden, anstatt Hunderte von Seiten zu konvertieren.

Also würde ich es nennen

encodingfinder.sh FILE Begrüßung

und das Skript testet, ob durch Konvertieren mit den bekannten Codierungen, die von ihnen "Begrüßung" erzeugen.

Um solche Charaktere zu finden, hilft normalerweise weniger, da funky Charaktere oft auffallen. Aus dem Kontext kann normalerweise das richtige Wort abgeleitet werden, nach dem gesucht werden soll. Wir möchten jedoch nicht mit einem Hexeditor überprüfen, um welches Byte es sich handelt, und dann endlose Codierungstabellen besuchen, um unseren Täter zu finden. :) :)

Benutzer unbekannt
quelle