Wie konvertiere ich diese Zeichenfolge mit GNU/Linux-Tools ins Japanische?

Wie konvertiere ich diese Zeichenfolge mit GNU/Linux-Tools ins Japanische?

Hier ist eine Zeichenfolge aus einer Textdatei:

@™TdaŽ®Æ‚êƒ~ƒNƒXƒgƒŒ[ƒgEƒrƒLƒjver1.11d1.d2iƒrƒLƒjƒ‚ƒfƒ‹ver.1.1³Ž®”z•z”Åj

Es enthält viele nicht druckbare Zeichen und wird hier kopiert:https://pastebin.com/TUG4agN4

Verwenden vonhttps://2cyr.com/decode/?lang=enkönnen wir bestätigen, dass es sich wie folgt übersetzen lässt:

 ☆Tda-Softwareupdater, -Update ...

Dies ist bei der Quellkodierung = SJIS (Shift-JIS), angezeigt als Windows-1252.

Aber wie können wir dasselbe Ergebnis ohne eine Website erzielen? Das relevante Tool ist iconv, aber etwas in der Toolkette ist kaputt. Wenn ich versuche, cat aus der Quelltextdatei zu verwenden oder sie als Standardeingabe mit '<' in bash zu verwenden, gibt eines der 'iconv's in der Kette schnell einen Fehler aus. Wenn ich die obige Zeichenfolge aus dem Texteditor gedit kopiere (der die Datei als utf-16le liest) oder als Ausgabe von iconv mit UTF16-zu-UTF8-Konvertierung, ist das Ergebnis ähnlich, aber immer noch falsch:

@儺da式ニれミクストレ[トEビキニver1.11d1.d2iビキニモデルver.1.1ウ式配布版j

Einige Hinweise auf das Versagen der Toolchain:

$ Katze 'utf8.txt' |Kopf -1

@™TdaŽ®Æ‚êƒ~ƒNƒXƒgƒŒ[ƒgEƒrƒLƒjver1.11d1.d2iƒrƒLƒjƒ‚ƒfƒ‹ver.1.1³Ž®”z•z”Å

$ cat 'utf8.txt' |head -1| iconv -f utf8 -t utf16

���@�"!Tda}��� ��~�N�X�g�R�[�g�E�r�L�jver1.11d1.d2�i�r�L�j� �f�9 ver.1.1��}� z" z ��j

Beachten Sie drei ungültige Zeichen am Anfang.

$ cat 'utf8.txt' |head -1| iconv -f utf8 -t utf16|iconv -f utf16 -t windows-1252

iconv: ungültige Eingabesequenz an Position 2

$ echo "@™TdaŽ®Æ‚êƒ~ƒNƒXƒgƒŒ[ƒgEƒrƒLƒjver1.11d1.d2iƒrƒLƒjƒ‚ƒfƒ‹ver.1.1³Ž®”z•z”Åj"| iconv -f utf8 -t utf16

��@"!Tda}�� ��~�N�X�g�R[�gE�r�L�jver1.11d1.d2i�r�L�j� �f�9 ver.1.1�}� z" z �j

Beachten Sie zwei ungültige Zeichen am Anfang und weitere Unterschiede. Die vom Terminal kopierte Sequenz stimmt mit der im Texteditor angezeigten Zeichenfolge überein, was durch die Suche (Strg-F) bestätigt wurde. Dies ist dieselbe Zeichenfolge, die auf 2cyr.com das richtige Ergebnis liefert.

Die Erweiterung des letzten Befehls oben mit „|iconv -f utf16 -t windows-1252|iconv -f shift-jis -t utf8“ führt zum ähnlichen, aber falschen Ergebnis wie oben, anstatt zu einem Fehler, wie es bei der direkten Kette der Fall ist.

Als ich versuchte, eine Datei mit dem Namen der Beispielzeichenfolge zu erstellen und das Tool convmv darauf anzuwenden, meldete convmv, dass der Ausgabedateiname „Zeichen enthält, die nicht POSIX-Dateisystem-konform sind! Dies kann zu Datenverlust führen.“ Die meisten Dateinamen, die mit UTF-8 ungültig sind, geben diese Warnung nicht aus.

Gibt es eine Bitfolge, die das Piping in Bash nicht verarbeiten kann? Wenn nicht, warum funktioniert die Toolchain nicht?

Der Unterschied liegt offenbar darin, dass Bash nicht druckbare Zeichen (die Kästchen mit Zahlen) nicht in die Befehlszeile einfügt. Vielleicht kann „readline“ sie nicht verarbeiten? Das Ergebnis ist jedoch ähnlich und lässt darauf schließen, dass die Konvertierungsreihenfolge in der Toolchain korrekt ist. Warum funktioniert es also nicht?

Die Originaldatei mit anders verschlüsseltem Dateinamen (läuft nach 30 Tagen ab):https://ufile.io/oorcq

Antwort1

Pipes sind eine Funktion des Betriebssystems, die mit Byte-Puffern arbeitet und deren Inhalt in keiner Weise interpretiert. Piped-Text gelangt also nicht zu Bash undbesondersniemals über „readline“. Text, der als Befehlszeilenargumente eingefügt wird, tut dies. (Und ja, sowohl readline als auch das Terminal können als Sicherheitsmaßnahme Steuerzeichen herausfiltern.)

Ihre Datei ist eigentlich eine Mischung aus zwei Kodierungen, windows-1252und iso8859-1zwar aufgrund der unterschiedlichen Verwendung des C1-Steuerzeichenblocks (0x80..0x9F).

  • ISO 8859-1 verwendet diesen gesamten Bereich für Steuerzeichen, und die Bytes 0x80..0x9F entsprechen den Unicode-Codepunkten U+0080..U+009F.
  • Windows-1252kann nichtstellen C1-Steuerzeichen dar; es nutzt den größten Teil dieses Bereichs für druckbare Zeichen und hat einige „Lücken“ – d. h. Bytewerte, denen nichts zugewiesen ist (0x81, 0x8D, 0x8F, 0x90, 0x9D).
  • Ansonsten sind die beiden Kodierungen in den Bereichen 0x00..0x7F und 0xA0..0xFF identisch.

Betrachten wir die erste Zeile Ihrer „fehlerhaften“ Eingabedatei, die von UTF-16 in Unicode-Text dekodiert und mit Escapezeichen für nicht druckbare Zeichen versehen wurde:

\u0081@\u0081™TdaŽ®\u008FÆ‚êƒ~ƒNƒXƒgƒŒ\u0081[ƒg\u0081EƒrƒLƒjver1.11d1.d2\u0081iƒrƒLƒjƒ‚ƒfƒ‹ver.1.1\u0090³Ž®”z•z”Å\u0081j\n
  • Sie können (U+0081) sehen \u0081, das dem Byte 0x81 in ISO 8859-1 entspricht, aber nicht in Windows-1252 codiert werden kann.
  • Sie können auch das Symbol ƒ(U+0192) sehen, das in Windows-1252 0x83 entspricht, in ISO 8859-1 jedoch überhaupt nicht existiert.

Der Trick besteht also darin, wenn möglich Windows-1252 und ISO 8859-1 als Fallback zu verwenden und für jeden Codepunkt einzeln zu entscheiden. (libiconv könnte dies über „ICONV_SET_FALLBACKS“ tun, das CLI- iconvTool jedoch nicht.) Sie können ganz einfach Ihr eigenes Tool schreiben:

#!/usr/bin/env python3
with open("/dev/stdin", "rb") as infd:
    with open("/dev/stdout", "wb") as outfd:
        for rune in infd.read().decode("utf-16"):
            try:
                chr = rune.encode("windows-1252")
            except UnicodeEncodeError:
                chr = rune.encode("iso8859-1")
            outfd.write(chr)
            # outputs shift-jis

Beachten Sie, dass nurHälfteIhrerEingabedateiist falsch kodiert, Shift-JIS. Die andere Hälfte (Englisch) ist vollkommen in Ordnung, UTF-16; glücklicherweise wird es von Shift-JIS durchgelassen, sodass keine manuelle Aufteilung erforderlich ist:

#!/usr/bin/env python3
with open("éΦé╟é▌üEé╓é╚é┐éσé▒éªéΦé⌐.txt", "r", encoding="utf-16") as infd:
    with open("りどみ・へなちょこえりか.txt", "w", encoding="utf-8") as outfd:
        buf = b""
        for rune in infd.read():
            try:
                buf += rune.encode("windows-1252")
            except UnicodeEncodeError:
                try:
                    buf += rune.encode("iso8859-1")
                except UnicodeEncodeError:
                    buf += rune.encode("shift-jis")
        outfd.write(buf.decode("shift-jis"))

verwandte Informationen