Ordenar no ordenar líneas con una tubería '|' en ello correctamente


17

Estoy tratando de ordenar algunos datos simples delimitados por tuberías. Sin embargo, ordenar no es realmente ordenar. Mueve mi fila de encabezado hacia abajo, pero mis dos filas que comienzan con 241 se dividen en una fila que comienza con 24.

cat sort_fail.csv
column_a|column_b|column_c
241|212|20810378
24|121|2810172
241|213|20810376

sort sort_fail.csv
241|212|20810378
24|121|2810172
241|213|20810376
column_a|column_b|column_c

Los encabezados de las columnas se están moviendo al final del archivo, por lo que ordenar los procesa claramente. Pero, los valores reales no se ordenan como era de esperar.

En este caso trabajé alrededor con

sort sort_fail.csv --field-separator='|' -k1,1

Pero, siento que eso no debería ser necesario. ¿Por qué ordenar no es ordenar?


2
uso LC_COLLATE=C sort. Dependiendo de lo que espere, también puede necesitarLC_COLLATE=C sort -t'|' -n
mosvy

3
Para ordenar los datos de "estilo" csv es posible que desee utilizar csvsortdesde csvkit, que trata los valores correctamente citado.
Bakuriu

Respuestas:


32

sort es compatible con la configuración regional, por lo que dependiendo de su configuración LC_COLLATE (que se hereda de LANG) puede obtener resultados diferentes:

$ LANG=C sort sort_fail.csv 
241|212|20810378
241|213|20810376
24|121|2810172
column_a|column_b|column_c

$ LANG=en_US sort sort_fail.csv
241|212|20810378
24|121|2810172
241|213|20810376
column_a|column_b|column_c

Esto puede causar problemas en los scripts, ya que es posible que no sepa qué configuración regional de llamada está configurada y, por lo tanto, puede obtener resultados diferentes.

No es raro que los scripts fuercen la configuración necesaria

p.ej

$ grep 'LC.*sort' /bin/precat
      LC_COLLATE=C sort -u | prezip-bin -z "$cmd: $2"

Ahora lo que es interesante, aquí, es que el |personaje se ve extraño.

Pero eso se debe a que la regla predeterminada para en_US, que deriva de ISO, dice

$ grep 007C /usr/share/i18n/locales/iso14651_t1_common
<U007C> IGNORE;IGNORE;IGNORE;<j> # 142 |

Lo que significa que el |personaje se ignora y el orden de clasificación sería como si el personaje no existiera.

$ tr -d '|' < sort_fail.csv | LANG=C sort
24121220810378
241212810172
24121320810376
column_acolumn_bcolumn_c

Y eso coincide con la clasificación "inesperada" que estás viendo.

Las soluciones alternativas son usar -n(para forzar ordenamientos numéricos), o usar el separador de campo (como lo hizo) o usar la Cconfiguración regional.


Fascinante. Vi algunos otros éxitos sobre la localización, pero pensé que eso afectaría el orden relativo de 24 frente a 241, no algo como esto.
user10777668

77
algo extra útil en GNU sort es la --debugopción, que indica la clave (subrayada) utilizada para comparar
Jeff Schaller

ejecutando con --debug solo subraya toda la línea - la ordenación incluye el carácter de la tubería, está configurado para no tener ningún impacto debido a la localización Es una buena característica, pero no me ayudó en este caso (lo intenté :)
user10777668

Es exactamente por eso que lo mencioné, @ user10777668: indica que sortestá usando toda la línea en lugar de detenerse en los caracteres que suponemos.
Jeff Schaller

No esperaba que se detuviera. Esperaba que reconociera el carácter de la tubería e lo incluyera en el género, por lo tanto, trato 24 | 1 y 241 de manera diferente. No estoy seguro de cómo --debug hubiera cambiado eso, y de hecho dado que subraya el | parece que se habría distraído activamente del problema real en el que la localización llevó a que se introdujera el carácter de la tubería
usuario10777668

1

Lo que me irrita es que 24no se mueve de su lugar entre los dos 241. El segundo campo comienza con a 1. Intentando el tipo con un líder 4en el segundo campo, 24se mueve hacia abajo, por lo que sospecho que sortsimplemente ignora a |menos que se indique lo contrario. Intenta sort -n...


1

-n, --numeric-sort compare según el valor numérico de la cadena

210
23

Sin el -n, 210 por texto está por delante de 23, ya que va personaje mi personaje.


Tienes razón, pero esto no explica que el char de tubería sea diferente. Las otras respuestas muestran que debido a la configuración regional, la tubería se trata como si no estuviera allí, por lo que el siguiente dígito es el que decide el orden.
Criggie
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.