2010-09-30 7 views
19

Ho un file di testo contenente ~ 300k righe. Ogni riga ha un numero variabile di campi delimitati da virgole, l'ultimo dei quali è garantito numerico. Voglio ordinare il file con questo ultimo campo numerico. Non posso fare:Bash: ordina il file di testo in base all'ultimo valore del campo

sort -t, -n -k 2 file.in > file.out 

come il numero di campi in ogni riga non è costante. Penso sed, awk forse la risposta, ma non so come. E.g:

awk -F, '{print $NF}' file.in 

mi dà l'ultimo valore di colonna, ma come utilizzarlo per ordinare il file?

risposta

27

Utilizzare awk per mettere in primo piano il tasto numerico. $NF è l'ultimo campo del record corrente. Ordinare. Usa sed per rimuovere la chiave duplicata.

awk -F, '{ print $NF, $0 }' yourfile | sort -n -k1 | sed 's/^[0-9][0-9]* //' 
+6

non c'è bisogno di reindirizzamento. 'awk -F, '{print $ NF, $ 0}' yourfile' – ghostdog74

0

Forse rovesciare i campi di ogni riga nel file prima di ordinare? Qualcosa come

perl -ne 'chomp; print(join(",",reverse(split(","))),"\n")' | 
    sort -t, -n -k1 | 
    perl -ne 'chomp; print(join(",",reverse(split(","))),"\n")' 

dovrebbe farlo, purché le virgole non vengano mai citate in alcun modo. Se si tratta di un file CSV a pieno titolo (in cui le virgole possono essere quotate con backslash o spazio), è necessario un parser CSV reale.

2
vim file.in -c '%sort n /.*,\zs/' -c 'saveas file.out' -c 'q' 
+1

Perché non usare 'ex' se avete intenzione di seguire questa strada? Vim ha comunque quella particolare funzionalità da "ex". –

+0

'ex' è solo' vim', con l'opzione '-e'. In questo caso non ha molta importanza. – Benoit

+0

'ex' precede' vim' (e 'vi') da parecchio tempo. 'vim' può avere una modalità di emulazione' ex', ma questo non lo rende 'ex'. –

0

Perl one-liner:

@lines=<STDIN>;foreach(sort{($a=~/.*,(\d+)/)[0]<=>($b=~/.*,(\d+)/)[0]}@lines){print;} 
0

ho intenzione di gettare miniera in qui come alternativa (e non ho potuto ottenere awk al lavoro) :)

file di esempio :

Call of Doody       1322 
Seam the Ripper       1329 
Mafia Bots 1       1109 
Chicken Fingers       1243 
Batup Light        1221 
Hunter F Tomcat       1140 
Tober         0833 

codice:

for i in `sed -e 's/.* \(\d\)*/\1/' file.txt | sort`; do grep $i file.txt; done > file_sort.txt 
0

Python one-liner:

python -c "print ''.join(sorted(open('filename'), key=lambda l: int(l.split(',')[-1])))"