Ordene el archivo CSV por prioridad de columna usando el comando "ordenar"

95

Tengo un archivo csv y me gustaría ordenarlo por prioridad de columna, como "ordenar por". Por ejemplo:

3;1;2
1;3;2
1;2;3
2;3;1
2;1;3
3;2;1

Si esta situación fuera el resultado de un "seleccionar", el "ordenar por" sería el siguiente: ordenar por columna2, columna1, columna3 - el resultado sería:

2;1;3
3;1;2
1;2;3
3;2;1
1;3;2
2;3;1

Me gustaría saber cómo obtener este mismo resultado usando el comando "sort" en Unix.

Rafael Orágio
fuente
4
Por cierto, es un archivo ssv (valores separados por punto y coma): P
John Strood

Respuestas:

157
sort --field-separator=';' --key=2,1,3
Charlie martin
fuente
9
Si los valores son numéricos, entonces probablemente desee considerar el uso de la -nopción que "comparará según el valor numérico de la cadena" o la -gopción que "comparará según el valor numérico general". Una comparación de cadenas de valores numéricos obtendrá los números ordenados como 1,10,2,20. Al menos esas son opciones disponibles en mi versión de sort en CentOS. Debe verificar con la página de manual cuáles son las opciones correctas en su versión de sort.
Adam Porad
5
Entiendosort: stray character in field spec: invalid field specification ‘2,1,3’
Martin Thoma
3
Sin embargo, sort --field-separator=',' -r -k3 -k1 -k2 source.csv > target.csvfuncionó para mí.
Martin Thoma
6
@MartinThoma ha pasado mucho tiempo, pero me encontré con tu problema y lo encontré sort --field-separator=';' --key={2,1,3}. Esto funcionó GNU coreutils 8.4desde abril de 2016
mrbolichi
3
@mrbolichi la notación --key={2,1,3}usa la expansión de
llaves
29

Suponga que tiene otra fila 3;10;3en su unsorted.csvarchivo. Entonces supongo que espera un resultado ordenado numéricamente:

2;1;3
3;1;2
1;2;3
3;2;1
1;3;2
2;3;1
3;10;3

y no ordenado alfabéticamente:

2;1;3
3;1;2
3;10;3
1;2;3
3;2;1
1;3;2
2;3;1

Para obtener eso, debes usar -n:

sort --field-separator=';' -n -k 2,2 -k 1,1 -k 3,3 unsorted.csv

Vale la pena mencionar que 2,2debe usarse. Si solo 2se usa, sorttoma la cadena desde el principio del campo 2 hasta el final. 2,2se asegura de que solo 2se utilice el campo .

Martín Thoma
fuente
8
¡El indicador de la diferencia entre -k 2 y -k 2,2 es significativo! Había pasado por alto esto en mi primera lectura de la página de manual. Gracias.
usonianhorizon
He añadido un par de filas adicionales, 3;10;3, 3:10:5, 3:10;2, 3;10;3en ese orden en el archivo de origen, y cuando se utiliza solo -k 2,2 aparece para ordenar en la columna 2 y 3. La página del manual dice "The -k option may be specified multiple times, in which case subsequent keys are compared when earlier keys compare equal.". En mi caso, la clave anterior (valor = 10) se comparó igual, sin embargo, no especifiqué -kvarias veces. No estoy seguro de si se trata de un comportamiento fiable o relacionado con mi sistema (mac). Sin embargo, en última instancia, no importa, siempre que la clasificación principal sea correcta.
Davos
Oh, veo que también hay -sun tipo estable que ignora las claves iguales, que aparentemente es más rápido según el hombre.
Davos
24

La respuesta de Charlie anterior no funcionó para mí en Cygwin (sort versión 2.0, GNU textutils), lo siguiente sí:

sort -t"," -k2 -k1 -k1
Samuel Kerrien
fuente
3
Cygwin tiene una versión anterior de sort. Como siempre, la página de manual es tu amiga.
Charlie Martin
2
Estoy de acuerdo con @CharlieMartin, debería consultar la página de manual de su sistema. En CentOS utilicésort --field-separator=';' -k2 -k1 -k3 test.csv
Adam Porad
-6

.. y si alguien siguió la solución 'ordenar' pero ahora quiere obtener más que la entrada única por línea (es decir, el número X superior de entradas únicas), una vez que haya ordenado el archivo usando 'ordenar', puede usar una pequeña aplicación que creé aquí:

https://github.com/danieliversen/MiscStuff/blob/master/scripts/findTopUniques.java

Daniel Iversen
fuente
2
¡Bien por usted! Pero en su caso, podría simplemente usar cat unsorted-file | sort | uniq | head -X- cuándo Xes el número de primeras filas que desea generar.
Slavik Meltser
@SlavikMe ¡Muchas gracias por el comentario! Sin embargo, su sugerencia da un resultado diferente. Su sugerencia obtiene las primeras X líneas en el archivo totalmente ordenado, mientras que nosotros queríamos obtener las primeras X líneas por "clave" (es decir, si tiene un CSV con nombres, entonces si ordena por la columna 2 "apellido" entonces sus comandos tal vez solo obtendrían 3 líneas con "Allen" como apellido, mientras que los nuestros obtendrían "Allen", "Brittain", "Charles", etc.). Pero gracias!
Daniel Iversen
6
Está usted equivocado. Sugeriría probar el comando que escribí antes de comentar. Tenga en cuenta que hay un comando uniqen el orden de las tuberías, entre el sorty el head, que da unicidad a todas las filas ordenadas justo antes de la extracción de las filas superiores.
Slavik Meltser