Ordinamento di più chiavi con ordinamento Unix


137

Ho file potenzialmente di grandi dimensioni che devono essere ordinati per chiavi 1-n. Alcuni di questi tasti potrebbero essere numerici e alcuni potrebbero non esserlo. Questo è un file colonnare a larghezza fissa, quindi non ci sono delimitatori.

C'è un buon modo per farlo con l'ordinamento Unix? Con una chiave è semplice come usare '-n'. Ho letto la pagina man e cercato brevemente su Google, ma non ho trovato un buon esempio. Come potrei fare per raggiungere questo obiettivo?

Nota: ho escluso Perl a causa del potenziale delle dimensioni del file. Sarebbe l'ultima risorsa.


Una o due righe di dati di esempio sarebbero davvero utili per creare la riga di comando di esempio. Inoltre, i tasti "1-n" indicano che è necessario ordinare in base a un numero variabile di tasti? Farlo senza script sarà divertente ...
Ken Gentle,

Ho un wrapper PHP attorno al comando sort per abilitare la funzione 1-n.
Chris Kloberdanz,

Risposte:


69

Utilizzare l' -kopzione (o --key=POS1[,POS2]). Può apparire più volte e ogni tasto può avere opzioni globali (come nper l'ordinamento numerico)


7
Dalla pagina man sort: "POS è F [.C] [OPTS], dove F è il numero del campo e C la posizione del carattere nel campo; entrambi sono origine 1." Vedi la pagina man per la documentazione completa.
Adam Rosenfield,

49
Vedi anche la risposta di andras se non vuoi diventare pazzo.
Ron,

1
Entrambi i commenti sopra sono accurati e additivi. Grazie signori.
Ken Gentle

314

Stai attento però:

Se vuoi ordinare il file principalmente per campo 3, e secondariamente per campo 2 vuoi questo:

sort -k 3,3 -k 2,2 < inputfile

Non questo: sort -k 3 -k 2 < inputfile che ordina il file in base alla stringa dall'inizio del campo 3 alla fine della riga (che è potenzialmente univoco).

-k, --key=POS1[,POS2]     start a key at POS1 (origin 1), end it at POS2
                          (default end of line)

8
Cambio vita. Grazie.
davidtbernal,

2
Ops! Ora devo correggere uno script perché in precedenza ho visto solo la prima risposta sopra ... buona cosa non ho ancora fatto affidamento sull'output dello script ....
Wildcard,

Bello! Ora, se volessi che il campo 3 fosse numericamente e in ordine inverso mentre il campo 2 fosse non numerico e normale (crescente)? :)
Arun,

2
@Arun POS è spiegato alla fine della pagina man. Basta aggiungere le opzioni di ordinazione al numero del campo in questo modo:sort -k 3,3nr -k 2,2
andras

1
Aargh. Che interfaccia controintuitiva: -k2dovrebbe essere -k2,2e una virgola finale -k2,dovrebbe essere "fine della linea di default magica o altro".
android.weasel,

94

L'opzione -k è ciò che vuoi.

-k 1.4,1.5n -k 1.14,1.15n

Userebbe le posizioni dei caratteri 4-5 nel primo campo (è tutto un campo per larghezza fissa) e ordinerebbe numericamente come il primo tasto.

La seconda chiave sarebbe rappresentata dai caratteri 14-15 anche nel primo campo.

(modificare)

Esempio (tutto quello che ho è DOS / cygwin a portata di mano):

dir | \cygwin\bin\sort.exe -k 1.4,1.5n -k 1.40,1.60r

per i dati:

12/10/2008  01:10 PM         1,564,990 outfile.txt

Ordina l'elenco delle directory in base al numero del mese (pos 4-5) numericamente, quindi al nome del file (pos 40-60) al contrario. Dal momento che non ci sono schede, è tutto il campo 1 da ordinare.


È solo un campo se non ci sono spazi vuoti nei dati di input. Tuttavia, il tuo esempio è utile.
Jonathan Leffler,

Correzione: se non ci sono / tabs / nei dati di input. Nell'output del comando 'dir' di DOS, non ci sono schede.
Clinton Pierce,

Gli esempi su come utilizzare le opzioni (numerico, inverso) sono estremamente utili, in quanto è quasi impossibile scoprire come utilizzare solo dalla pagina man e le altre risposte non ne hanno parlato. Vorrei poter fare +2 per questo. ;)
msb

22

Ecco uno per ordinare varie colonne in un file CSV in ordine numerico e di dizionario, colonne 5 e successive come ordine di dizionario

~/test>sort -t, -k1,1n -k2,2n -k3,3d -k4,4n -k5d  sort.csv
1,10,b,22,Ga
2,2,b,20,F
2,2,b,22,Ga
2,2,c,19,Ga
2,2,c,19,Gb,hi
2,2,c,19,Gb,hj
2,3,a,9,C

~/test>cat sort.csv
2,3,a,9,C
2,2,b,20,F
2,2,c,19,Gb,hj
2,2,c,19,Gb,hi
2,2,c,19,Ga
2,2,b,22,Ga
1,10,b,22,Ga

Nota -k1,1n significa numerico che inizia alla colonna 1 e termina alla colonna 1. Se avessi fatto di seguito, avrebbe concatenato le colonne 1 e 2 facendo 1,10 ordinati come 110

~/test>sort -t, -k1,2n -k3,3 -k4,4n -k5d  sort.csv
2,2,b,20,F
2,2,b,22,Ga
2,2,c,19,Ga
2,2,c,19,Gb,hi
2,2,c,19,Gb,hj
2,3,a,9,C
1,10,b,22,Ga

1
Questa è la risposta migliore perché mostra come utilizzare switch diversi per colonne diverse
xaxa,

12

Credo nel tuo caso qualcosa del genere

sort -t@ -k1.1,1.4 -k1.5,1.7 ... <inputfile

funzionerà meglio. @ è il separatore di campo, assicurati che sia un carattere che non appare da nessuna parte. quindi il tuo input è considerato costituito da una colonna.

Modifica: apparentemente clintp ha già dato una risposta simile, scusa. Come sottolinea, le bandiere 'n' e 'r' possono essere aggiunte ad ogni opzione -k ....


Anche se il separatore predefinito secondo i documenti gnu.org/software/coreutils/manual/html_node/… è lo spazio, a volte il conteggio dei campi non è quello che ti aspetteresti. Forse come altri hanno già detto qui a causa delle impostazioni locali di LC_CTYPE. In caso di dubbi conta dall'inizio della riga!
Brad Dre,

5

Si noti che si può anche desiderare di stabilizzare l'ordinamento con l' -sinterruttore, in modo che linee ugualmente classificate mantengano il loro ordine relativo originale anche nell'output.


2

Voglio solo aggiungere alcuni suggerimenti, quando si utilizza l'ordinamento, fare attenzione alle impostazioni locali che influiscono sull'ordine del confronto chiave. Di solito uso esplicitamente LC_ALL = C per rendere le impostazioni locali ciò che voglio.


LC_ALL = C può anche comportare un notevole aumento di velocità!
mat kelcey,
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.