GNU/Linux ツールを使用してこの文字列を日本語に変換するにはどうすればよいでしょうか?

GNU/Linux ツールを使用してこの文字列を日本語に変換するにはどうすればよいでしょうか?

以下はテキスト ファイルからの文字列です。

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

これには多くの非印刷文字が含まれており、ここにコピーされます:https://pastebin.com/TUG4agN4

使用https://2cyr.com/decode/?lang=en次のように翻訳されることを確認できます。

 ☆Tda式照れミクストレート・ビキニver1.11d1.d2(ビキニモデルver.1.1正式配布版)

これはソースエンコーディング = SJIS (shift-jis) で、Windows-1252 として表示されます。

しかし、Web サイトなしで同じ結果を得るにはどうしたらよいでしょうか。関連するツールは iconv ですが、ツール チェーン内の何かが壊れています。ソース テキスト ファイルから cat を実行しようとしたり、bash で '<' を使用して標準入力として使用したりすると、チェーン内の 'iconv' の 1 つですぐにエラーが発生します。上記の文字列をテキスト エディター gedit (ファイルを utf-16le として読み取る) からコピーするか、iconv で utf16 から utf8 への変換を行って出力した場合、結果は近いものの、まだ間違っています。

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

ツール チェーンが失敗したことを示す証拠:

$ cat 'utf8.txt' |head -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

先頭に無効な文字が 3 つあることに注意してください。

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

iconv: 位置 2 の入力シーケンスが不正です

$ echo "@™TdaŽ®Æ‚êƒ~ƒNƒXƒgƒŒ[ƒgEƒrƒLƒjver1.11d1.d2iƒrƒLƒjƒ‚ƒfƒ‹ver.1.1³Ž®”z•z”Åj"|アイコンv -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

先頭の 2 つの無効な文字とその他の違いに注意してください。ターミナルからコピーされたシーケンスは、テキスト エディターに表示される文字列と一致します。これは、一致する検索 (Ctrl + F) によって確認され、2cyr.com で正しい結果を返す文字列と同じです。

上記の最後のコマンドを '|iconv -f utf16 -t windows-1252|iconv -f shift-jis -t utf8' で拡張すると、直接チェーンのようにエラーが発生するのではなく、上記で引用したのに近いが正しくない結果が生成されます。

サンプル文字列という名前のファイルを作成し、そのファイルに対してツール convmv を使用しようとすると、convmv は出力ファイル名に「POSIX ファイルシステムに準拠していない文字が含まれています。これにより、データが失われる可能性があります。」と表示しました。UTF-8 で無効なファイル名のほとんどは、この警告を表示しません。

bash のパイプ処理で処理できないビット シーケンスはありますか? そうでない場合、ツール チェーンが機能しないのはなぜですか?

どうやら、違いは、bash が非印刷文字 (数字の入ったボックス) をコマンド ラインに貼り付けないためのようです。おそらく 'readline' はそれらを処理できないのでしょうか? しかし、結果が近いということは、ツールチェーンの変換順序が正しいことを示しています。では、なぜ機能しないのでしょうか?

ファイル名が別の方法でスクランブルされた元のファイル (30 日後に有効期限が切れます):https://ufile.io/oorcq

答え1

パイプはバイトバッファで動作するOSの機能であり、その内容を解釈することはありません。そのため、パイプされたテキストはbashに渡されず、特に'readline' を経由することはありません。コマンドライン引数として貼り付けられたテキストは経由します。(そして、はい、readline とターミナルの両方がセキュリティ対策として制御文字をフィルタリングする場合があります。)

ファイルは、C1 制御文字ブロック (0x80..0x9F) の使用方法が異なるため、windows-1252実際には と の 2 つのエンコードが混在しています。iso8859-1

  • ISO 8859-1 では、この範囲全体を制御文字に使用し、バイト 0x80..0x9F は Unicode コードポイント U+0080..U+009F に対応します。
  • Windows-1252できないC1 制御文字を表します。この範囲のほとんどを印刷可能な文字に使用し、いくつかの「穴」、つまり何も割り当てられていないバイト値 (0x81、0x8D、0x8F、0x90、0x9D) があります。
  • それ以外の点では、2 つのエンコーディングは 0x00..0x7F および 0xA0..0xFF の範囲では同一です。

UTF-16 から Unicode テキストにデコードされ、印刷できない文字がエスケープされた「不良」入力ファイルの最初の行を見てみましょう。

\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
  • (U+0081)は\u0081、ISO 8859-1 のバイト 0x81 にマップされますが、Windows-1252 ではエンコードできません。
  • ƒまた、Windows-1252 では 0x83 にマッピングされるが、ISO 8859-1 にはまったく存在しないシンボル (U+0192) も表示されます。

したがって、秘訣は、可能な場合は Windows-1252 を使用し、フォールバックとして ISO 8859-1 を使用し、コードポイントごとに個別に決定することです。(libiconv は 'ICONV_SET_FALLBACKS' を介してこれを実行できますが、CLIiconvツールでは実行できません。) 独自のツールを作成するのは簡単です。

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

ただし、半分あなたの入力ファイルは Shift-JIS で誤ってエンコードされています。もう半分 (英語) は UTF-16 で問題ありません。幸い Shift-JIS はそのまま通過するため、手動で分割する必要はありません。

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

関連情報