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.