Tengo un conjunto de archivos de texto razonablemente grande (~15 GB). Estos archivos son esencialmente bases de datos simples que contienen credenciales, y las credenciales que contienen a menudo se encuentran fuera del rango ASCII de 128 caracteres (caracteres acentuados y similares).
Cuando intento ordenar algunos de estos archivos con:
sort -u input.txt -o output.txt
...Obtuve el siguiente error:
sort: string comparison failed: Invalid or incomplete multibyte or wide character
sort: Set LC_ALL='C' to work around the problem.
He leído mucho sobre cómo el uso LC_ALL=C
puede acelerar los comandos que tratan con caracteres, como sort
y grep
, incluidosLa brillante respuesta de Stéphane Chazelassobre el tema, pero me preocupan específicamente las implicaciones de usarlo en mi conjunto de datos.
¿Es probable que la ejecución LC_ALL=C sort -u
de estos archivos les quite cualquier carácter que no sea ASCII?
Si esto es, entonces, ¿qué puedo hacer para arreglar/eliminar todo?caracteres anchos o multibyte no válidos o incompletos" de estos archivos, lo que me permite ordenarlos sin utilizar LC_ALL=C
?
Respuesta1
¿Es probable que la ejecución de LC_ALL=C sort -u en estos archivos les quite cualquier carácter que no sea ASCII?
En este caso no, no; sort
simplemente trabajará directamente en los valores de bytes en lugar de intentar convertirlos en caracteres.
Sin embargo, no ocurre necesariamente lo mismo con otras herramientas. Los programas escritos en C (el lenguaje) son los que tienen más probabilidades de comportarse de esta manera. Los programas escritos en lenguajes con una fuerte distinción entre bytes y caracteres, como en Python 3, deberían negarse rotundamente a aceptar entradas que no se ajusten al conjunto de caracteres. Y ciertamente puedo imaginar programas mal escritos que ignoran los errores y generan ?
en su lugar una � o una.
Si es así, entonces, ¿qué puedo hacer para arreglar/eliminar todos los "caracteres anchos o multibyte no válidos o incompletos" de estos archivos, permitiéndome ordenarlos sin usar LC_ALL=C?
Asegúrese de que todos estén usando la misma codificación de archivo (preferiblemente UTF-8) y de que su configuración regional esté usando la misma codificación. El error nunca debería ocurrir para un archivo UTF-8 válido, sin importar cuán grande sea.
Respuesta2
Debido a que terminé necesitando canalizar mis archivos a través de muchas herramientas Bash diferentes como , , y sort
, grep
decidí awk
que era más seguro buscar la "solución adecuada" indicada en la respuesta aceptada; convirtiéndolos todos a UTF-8 primero. Esto terminó siendo un poco más difícil de lo esperado, sobre todo porque me tomó un tiempo darme cuenta de que no es confiable para determinar si un archivo es ASCII o UTF-8 (porque no verifica la totalidad del archivo). así que dejo esta respuesta aquí para la posteridad.wc
tr
file
Para determinar definitivamente en qué codificación están sus archivos, primero asegúrese de que el uchardet
paquete esté instalado a través del instalador de Cygwin oapt-cyg, entonces corre:
uchardet *.txt
O si no estás en Cygwin:
chardet *.txt
Mueva todos los archivos que chardet
aparecen en la lista ASCII
a una carpeta propia y ejecute el siguiente for
bucle en esa carpeta:
for i in *.txt; do iconv -f ASCII -t UTF-8 "$i" >> "${i%.txt}_utf.txt"; done;
Recorrerá todos .txt
los archivos de una carpeta y creará versiones UTF-8 de ellos con el utf
sufijo agregado.
Al volver a ejecutarlo uchardet *.txt
, es posible que aún se muestren algunos archivos como ASCII
. Esto sucede porque ASCII es un subconjunto de UTF-8 ysimplemente significaque esos archivos no contengan caracteres fuera del rango ASCII de 128 bits.
Ahora debería poder ejecutar sort
sin necesidad de utilizar LC_ALL=C
.