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式光れMikstreet・비키니ver1.11d1.d2(비키니모델ver.1.1정式配布版)

이는 소스 인코딩 = SJIS(shift-jis)이며 Windows-1252로 표시됩니다.

하지만 웹사이트 없이 어떻게 동일한 결과를 얻을 수 있습니까? 관련 도구는 iconv이지만 도구 체인의 일부가 손상되었습니다. 소스 텍스트 파일에서 cat을 시도하거나 bash에서 '<'를 사용하여 표준 입력으로 사용하려고 하면 체인의 'iconv' 중 하나에서 빠르게 오류가 발생합니다. 위 문자열을 텍스트 편집기 gedit(utf-16le로 파일 읽기)에서 복사하거나 utf16-to-utf8 변환을 통해 iconv의 출력으로 복사하면 결과는 비슷하지만 여전히 잘못된 것입니다.

@儺da式ニれMiks스트레[트Ebikiniver1.11d1.d2ibikinini모델ver.1.1ウ式配布版j

도구 체인이 실패했다는 몇 가지 증거:

$ 고양이 'utf8.txt' |머리 -1

@™Tda®Æ‚êf~åNáXògáŒ[ÃgEärðLÃjver1.11d1.d2i°r°L°jüfòver.1.1³®”z•z”Å

$ cat 'utf8.txt' |헤드 -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' |헤드 -1| iconv -f utf8 -t utf16|iconv -f utf16 -t windows-1252

iconv: 위치 2의 입력 시퀀스가 ​​잘못되었습니다.

$ echo "@™Tda®Æ‚êf~́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

시작 시 두 개의 유효하지 않은 문자와 다른 차이점을 참고하세요. 터미널에서 복사된 시퀀스는 텍스트 편집기에 표시된 문자열과 일치하며, 일치하는 찾기(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.iso8859-1

  • ISO 8859-1은 제어 문자에 이 전체 범위를 사용하며 바이트 0x80..0x9F는 유니코드 코드 포인트 U+0080..U+009F에 해당합니다.
  • 윈도우-1252할 수 없다C1 제어 문자를 나타냅니다. 이는 인쇄 가능한 문자에 대해 이 범위의 대부분을 사용하며 몇 가지 "구멍"(즉, 아무것도 할당되지 않은 바이트 값(0x81, 0x8D, 0x8F, 0x90, 0x9D))을 갖습니다.
  • 두 인코딩은 0x00..0x7F 및 0xA0..0xFF 범위에서 동일합니다.

UTF-16에서 유니코드 텍스트로 디코딩되고 인쇄할 수 없는 문자가 이스케이프된 "잘못된" 입력 파일의 첫 번째 줄을 살펴보겠습니다.

\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
  • \u0081ISO 8859-1에서는 바이트 0x81에 매핑되지만 Windows-1252에서는 인코딩할 수 없는 (U+0081)을 볼 수 있습니다 .
  • ƒWindows-1252에서는 0x83으로 매핑되지만 ISO 8859-1에서는 전혀 존재하지 않는 기호(U+0192)도 볼 수 있습니다 .

따라서 가능한 경우 Windows-1252를 사용하고 ISO 8859-1을 대체 수단으로 사용하여 각 코드 포인트에 대해 개별적으로 결정하는 것이 좋습니다. (libiconv는 'ICONV_SET_FALLBACKS'를 통해 이 작업을 수행할 수 있지만 CLI iconv도구는 수행할 수 없습니다.) 자신만의 도구를 작성하는 것은 쉽습니다.

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

관련 정보