¿Cómo convertir esta cadena al japonés usando herramientas GNU/Linux?

¿Cómo convertir esta cadena al japonés usando herramientas GNU/Linux?

Aquí hay una cadena de un archivo de texto:

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

Incluye muchos caracteres no imprimibles y se copia aquí:https://pastebin.com/TUG4agN4

Usandohttps://2cyr.com/decode/?lang=en, podemos confirmar que se traduce en lo siguiente:

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

Esto es con codificación fuente = SJIS (shift-jis), que se muestra como Windows-1252.

Pero ¿cómo podemos obtener el mismo resultado sin un sitio web? La herramienta relevante es iconv, pero algo en la cadena de herramientas está roto. Si intento extraer el archivo de texto fuente o usarlo como entrada estándar con '<' en bash, uno de los 'iconv's de la cadena falla rápidamente. Si copio la cadena anterior del editor de texto gedit (leyendo el archivo como utf-16le) o como salida de iconv con conversión de utf16 a utf8, entonces el resultado es cercano, pero sigue siendo incorrecto:

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

Algunas pruebas de que la cadena de herramientas está fallando:

$ gato 'utf8.txt' |cabeza -1

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

$ gato 'utf8.txt' |cabeza -1| iconov -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

Tenga en cuenta tres caracteres no válidos al principio.

$ gato 'utf8.txt' |cabeza -1| iconv -f utf8 -t utf16|iconv -f utf16 -t windows-1252

iconv: secuencia de entrada ilegal en la posición 2

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

Tenga en cuenta dos caracteres no válidos al principio y otras diferencias. La secuencia copiada del terminal coincide con la cadena que se muestra en el editor de texto, confirmada al buscar (ctrl-F) que coincida, que es la misma cadena que da el resultado correcto en 2cyr.com.

Extender el último comando anterior con '|iconv -f utf16 -t windows-1252|iconv -f shift-jis -t utf8' da el resultado cercano, pero incorrecto, citado anteriormente, en lugar de generar errores como lo hace la cadena directa.

Si intenté crear un archivo llamado cadena de ejemplo y usar la herramienta convmv en él, convmv dijo que el nombre del archivo de salida contenía "caracteres que no se ajustan al sistema de archivos POSIX. Esto puede provocar la pérdida de datos". La mayoría de los nombres de archivos que no son válidos con UTF-8 no dan esta advertencia.

¿Hay alguna secuencia de bits que la tubería en bash no pueda manejar? Si no, ¿por qué no funciona la cadena de herramientas?

Aparentemente, la diferencia se debe a que bash no pega caracteres que no se imprimen (los cuadros con números) en la línea de comando; ¿Quizás 'readline' no pueda manejarlos? Pero el hecho de que el resultado sea cercano sugiere que el orden de conversión en la cadena de herramientas es correcto, entonces, ¿por qué no funciona?

El archivo original, con su nombre codificado de forma diferente (caduca después de 30 días):https://ufile.io/oorcq

Respuesta1

Las canalizaciones son una característica del sistema operativo que funciona con buffers de bytes y no interpreta su contenido de ninguna manera. Entonces el texto canalizado no pasa a bash yespecialmentenunca a través de 'readline'. Texto pegado como lo hacen los argumentos de la línea de comandos. (Y sí, tanto readline como el terminal pueden filtrar los caracteres de control como medida de seguridad).

Su archivo es en realidad una combinación de dos codificaciones windows-1252y iso8859-1, debido a las diferentes formas en que usan el bloque de caracteres de control C1 (0x80..0x9F).

  • ISO 8859-1 utiliza todo este rango para caracteres de control, y los bytes 0x80..0x9F corresponden a los puntos de código Unicode U+0080..U+009F.
  • Windows-1252no puedorepresentar caracteres de control C1; utiliza la mayor parte de este rango para caracteres imprimibles y tiene algunos "huecos", es decir, valores de bytes que no tienen nada asignado (0x81, 0x8D, 0x8F, 0x90, 0x9D).
  • Por lo demás, las dos codificaciones son idénticas en los rangos 0x00..0x7F y 0xA0..0xFF.

Tomemos la primera línea de su archivo de entrada "malo", decodificado de UTF-16 a texto Unicode y con caracteres no imprimibles escapados:

\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
  • Puede ver \u0081(U+0081), que se asigna al byte 0x81 en ISO 8859-1 pero no se puede codificar en Windows-1252.
  • También puede ver el símbolo ƒ(U+0192), que se asigna a 0x83 en Windows-1252 pero no existe en absoluto en ISO 8859-1.

Entonces, el truco consiste en usar Windows-1252 cuando sea posible e ISO 8859-1 como alternativa, decidiendo individualmente para cada punto de código. (libiconv podría hacer esto a través de 'ICONV_SET_FALLBACKS', pero la iconvherramienta CLI no puede). Es fácil escribir su propia herramienta:

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

Tenga en cuenta que sólomediode tufichero de entradaestá mal codificado Shift-JIS. La otra mitad (inglés) está perfectamente bien en UTF-16; afortunadamente, Shift-JIS lo pasará por lo que no es necesaria la división manual:

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

información relacionada