Ordina il file CSV per priorità di colonna utilizzando il comando "sort"


91

Ho un file csv e vorrei ordinarlo in base alla priorità della colonna, ad esempio "ordina per". Per esempio:

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

Se questa situazione fosse il risultato di una "selezione", l '"ordina per" sarebbe il seguente: ordina per colonna2, colonna1, colonna3 - il risultato sarebbe:

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

Mi piacerebbe sapere come ottenere lo stesso risultato usando il comando "sort" su Unix.


4
A proposito, questo è un file ssv (valori separati da punto e virgola): P
John Strood

Risposte:


153
sort --field-separator=';' --key=2,1,3

8
Se i valori sono numerici, probabilmente vorrai considerare l'utilizzo -ndell'opzione che "confronterà in base al valore numerico della stringa" o l' -gopzione che "confronterà in base al valore numerico generale". Un confronto tra stringhe di valori numerici otterrà i numeri ordinati come 1,10,2,20. Almeno quelle sono opzioni disponibili sulla mia versione di sort su CentOS. Dovresti verificare con la pagina man quali sono le opzioni corrette nella tua versione di sort.
Adam Porad

4
Ottengosort: stray character in field spec: invalid field specification ‘2,1,3’
Martin Thoma

3
Tuttavia, ha sort --field-separator=',' -r -k3 -k1 -k2 source.csv > target.csvfunzionato per me.
Martin Thoma

6
@MartinThoma è passato molto tempo ma mi sono imbattuto nel tuo problema e l'ho trovato sort --field-separator=';' --key={2,1,3}. Questo ha funzionato GNU coreutils 8.4da aprile 2016
mrbolichi

2
@mrbolichi la notazione --key={2,1,3}utilizza l'espansione delle parentesi graffe di bash
kvantour

28

Supponi di avere un'altra riga 3;10;3nel tuo unsorted.csvfile. Quindi immagino che ti aspetti un risultato ordinato numericamente:

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

e non uno in ordine alfabetico:

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

Per ottenerlo, devi usare -n:

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

Vale la pena ricordare che 2,2deve essere utilizzato. Se 2viene utilizzato solo , sortprende la stringa dall'inizio del campo 2 alla fine. 2,2si assicura che 2venga utilizzato solo il campo .


7
Il puntatore sulla differenza tra -k 2 e -k 2,2 è significativo! L'avevo trascurato nella mia prima lettura della pagina man. Grazie.
usonianhorizon

Ho aggiunto un paio di righe in più, 3;10;3, 3:10:5, 3:10;2, 3;10;3in questo ordine nel file di origine, e quando si utilizza solo -k 2,2 appare per ordinare su colonna 2 e 3. La pagina man dice "The -k option may be specified multiple times, in which case subsequent keys are compared when earlier keys compare equal.". Nel mio caso la chiave precedente (valore = 10) è risultata uguale, tuttavia, non ho specificato -kpiù volte. Non sono sicuro che si tratti di un comportamento affidabile o correlato al mio sistema (mac). Alla fine, non importa, purché l'ordinamento principale sia corretto.
Davos

Oh vedo che esiste anche -sun ordinamento stabile che ignora le chiavi di uguale, che è apparentemente più veloce secondo l'uomo.
Davos

24

La risposta di Charlie sopra non ha funzionato per me su Cygwin (tipo versione 2.0, GNU textutils), quanto segue ha funzionato:

sort -t"," -k2 -k1 -k1

3
Cygwin ha una versione precedente di sort. Come sempre, la pagina man è tua amica.
Charlie Martin

2
Sono d'accordo con @CharlieMartin, dovresti controllare la pagina man sul tuo sistema. Su CentOS ho usatosort --field-separator=';' -k2 -k1 -k3 test.csv
Adam Porad

-6

..e se qualcuno ha seguito la soluzione "ordina" ma ora desidera ottenere più della singola voce univoca per riga (ovvero il numero X superiore di voci univoche), una volta ordinato il file utilizzando "ordina", è possibile utilizzare una piccola app che ho creato qui:

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


2
Buon per te! Ma nel tuo caso, potresti semplicemente usare cat unsorted-file | sort | uniq | head -X- quando Xè il numero delle prime righe che desideri produrre.
Slavik Meltser

@SlavikMe Grazie mille per il commento! Tuttavia, il tuo suggerimento dà un risultato diverso .. Il tuo suggerimento ottiene le prime X righe nel file completamente ordinato, mentre noi volevamo ottenere le prime X righe per "chiave" (cioè se hai un CSV con nomi, poi se ordini per la colonna 2 "cognome", i tuoi comandi potrebbero ricevere solo 3 righe con "Allen" come cognome, mentre i nostri otterrebbero "Allen", "Brittain", "Charles" ecc.). Grazie comunque!
Daniel Iversen

6
Tui hai torto. Avrei suggerito di provare il comando che ho scritto prima di commentare. Notare che esiste un comando uniqnell'ordine delle pipe, tra il sorte il head, che dà un'unicità a tutte le righe ordinate appena prima dell'estrazione delle righe superiori.
Slavik Meltser
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.