Tengo un archivo TXT, que se envía desde una máquina Windows y está codificado en ISO-8859-1 . Se supone que mi aplicación Qt lee este archivo pero QString solo admite UTF-8 (quiero evitar trabajar con QByteArray). He estado luchando por encontrar una manera de hacerlo en Qt, así que decidí escribir un pequeño guión que haga la conversión por mí. No tengo ningún problema para escribirlo exactamente para mi caso, pero me gustaría hacerlo más general, para toda la codificación ISO-8859.

Hasta ahora tengo lo siguiente:

#!/usr/bin/env bash

output=$(file -i $1)

# If the output contains any sort of ISO-8859 substring
if echo "$output" | grep -qi "ISO-8859"; then
  # Retrieve actual encoding
  encoding=...
  # run iconv to convert
  iconv -f $encoding $1 -t UTF-8 -o $1
else
  echo "Text file not encoded in ISO-8859"
fi

La parte con la que estoy luchando es cómo obtener la subcadena completa que se ha emparejado con éxito en el comando grep.

Digamos que tengo el archivo helloworld.txt y está codificado en ISO-8859-15. En este caso

$~: ./fixEncodingToUtf8 helloworld.txt
stations.txt: text/plain; charset=iso-8859-15

Será el output en la terminal. Internamente, grep encuentra el iso-8859 (ya que uso el indicador -i, procesa la entrada sin distinción entre mayúsculas y minúsculas). En este punto, el script necesita "extraer" toda la subcadena, es decir, no solo iso-8859 sino iso-8859-15 y almacenarla dentro de la variable encoding para usarla más tarde con iconv (que no distingue entre mayúsculas y minúsculas (¡uf!) cuando se trata del nombre de las codificaciones).

NOTA: la secuencia de comandos anterior se puede ampliar aún más simplemente recuperando el valor que sigue a charset y usándolo para encoding. Sin embargo, esto tiene un gran defecto: ¿qué sucede si el archivo de entrada tiene una codificación que tiene un conjunto de caracteres más grande que UTF-8 (ejemplo simple: UTF-16 y UTF-32)?

1
rbaleksandar 18 oct. 2017 a las 16:38

3 respuestas

La mejor respuesta

Bueno, en este caso no tiene sentido ...

$ file --brief --mime-encoding "$1"
iso-8859-15

archivo manual

-b, --brief
        Do not prepend filenames to output lines (brief mode).
...
--mime-type, --mime-encoding
        Like -i, but print only the specified element(s).
1
pacholik 18 oct. 2017 a las 14:18

Puede usar cut o awk para llegar a esto:

Awk:

encoding=$(echo $output | awk -F"=" '{print $2}')

Cortar:

encoding=$(echo $output | cut -d"=" -f2)

Creo que podría pasar esto directamente a su comando iconv y reducir su script a:

iconv -f $(file $1 | cut -d"=" -f2) -t UTF-8 file
2
JNevill 18 oct. 2017 a las 13:58

O usando las funciones de bash como a continuación

$ str="stations.txt: text/plain; charset=iso-8859-15"
$ echo "${str#*=}"
iso-8859-15

Para guardar en variable

$ myvar="${str#*=}"
2
Akshay Hegde 18 oct. 2017 a las 13:56