Come eseguire l'ordinamento personalizzato utilizzando l'ordinamento unix?


11

Sto usando unix sort per ordinare un file delimitato da virgole con più colonne. Finora, questo ha funzionato perfettamente per ordinare i dati in ordine numerico o in ordine alfabetico:

File di esempio prima di qualsiasi ordinamento:

C,United States,WA,Tacoma,f,1
A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,Canada,QC,Montreal,f,2
A,Bahamas,Bahamas,Nassau,f,2
A,United States,NY,New York,f,1

Ordina il file: $ sort -t ',' -k 2,2 -k 3,3 -k 4,4 -k 5,5r -k 6,6nr tmp.csv

Risultato ordinato:

A,Bahamas,Bahamas,Nassau,f,2
A,Canada,QC,Montreal,f,2
A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,United States,NY,New York,f,1
C,United States,WA,Tacoma,f,1

Ecco il problema: voglio ordinare la colonna 2 in base a un ordinamento personalizzato, il che significa che voglio prima gli Stati Uniti, poi il Canada, quindi le Bahamas:

Ordinamento desiderato:

A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,United States,NY,New York,f,1
C,United States,WA,Tacoma,f,1
A,Canada,QC,Montreal,f,2
A,Bahamas,Bahamas,Nassau,f,2

C'è un modo per passare unix ordinamento un ordinamento personalizzato che può quindi applicare? Qualcosa di simile a: $ sort -t ',' -k 2,2:'United States, Canada, Bahamas' -k 3,3 -k 4,4 -k 5,5r -k 6,6nr tmp.csv

Grazie!


3
Per questi tre valori, si desidera l'ordine alfabetico inverso. Per il caso generale, è necessario mappare i nomi su un numero di ordinamento, quindi eseguire l'ordinamento utilizzando il numero di ordinamento. Oppure scegli un linguaggio di scripting ... Una possibilità è il joincomando, ma potresti finire con un sacco di ordinamento: i file di input per joindevono essere ordinati in un ordine, e quindi useresti di sortnuovo per inserire i dati in un ordine diverso (e perdere la colonna di ordinamento come passaggio post-ordinamento).
Jonathan Leffler,

Nel tuo esempio di input, non dovrebbe esserci tinvece fnell'ultima riga?
Lev Levitsky,

Lev: sì, buona cattura. Colpa mia; troppo taglio e incolla (il mio set di dati effettivo è molto più grande e ho accidentalmente preso le righe sbagliate).

Ho aggiornato la risposta per abbinare i tuoi dati.
Lev Levitsky,

Risposte:


8

L'altra risposta e commento rispondono alla domanda in generale, ecco come può apparire un'implementazione:

$ cat order
Bahamas,3
Canada,2
United States,1

$ cat data
C,United States,WA,Tacoma,f,1
A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,Canada,QC,Montreal,f,2
A,Bahamas,Bahamas,Nassau,f,2
A,United States,NY,New York,f,1

$ sort -t, -k2 data | join -t, -11 -22 order - | sort -t, -k2n -k4,5 -k6r -k7nr | cut -d, -f 3,1,4-7
A,United States,MA,Boston,f,0
B,United States,NY,New York,f,5
A,United States,NY,New York,f,1
C,United States,WA,Tacoma,f,1
A,Canada,QC,Montreal,f,2
A,Bahamas,Bahamas,Nassau,f,2

Fantastico, grazie per il tuo aiuto. Questo ha funzionato perfettamente!

@jewelia Migliorato ancora una volta, sednon era davvero necessario qui.
Lev Levitsky,

1

Non puoi farlo con l' ordinamento . A questo punto, dovresti davvero raggiungere awk / perl / la tua lingua preferita . Puoi confonderlo, comunque. Ad esempio, è possibile utilizzare sed per modificare "Stati Uniti" su 0, "Canada" su 1 e "Bahamas" su 2, quindi eseguire un ordinamento numerico su quella colonna, quindi ripristinarlo. O cambia "Stati Uniti" in "Stati Uniti, 0" ecc., Ordina la colonna aggiuntiva e poi scartala.


0

Ho appena scritto un aiutante chiamato csort per renderlo facile. Prefissa ogni riga con un valore di tua scelta in base alla sottostringa o alle corrispondenze di espressioni regolari all'interno della riga:

$ csort -t, '2=United States' X 2=Canada Y 2=Bahamas Z < tmp.csv | \
sort -t, -k1,1 -k3,3 -k4,4 -k5,5 -k6,6r -k7,7nr
X,A,United States,MA,Boston,f,0
X,B,United States,NY,New York,f,5
X,A,United States,NY,New York,f,1
X,C,United States,WA,Tacoma,f,1
Y,A,Canada,QC,Montreal,f,2
Z,A,Bahamas,Bahamas,Nassau,f,2

La 2=STRnotazione significa "match se il secondo campo è uguale STR".

È quindi possibile reindirizzare facoltativamente l'output cut -c3-per rimuovere il prefisso.

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.