2010-09-30 1 views
19

J'ai un fichier texte contenant ~ 300k lignes. Chaque rangée a un nombre variable de champs délimités par des virgules, dont le dernier est garanti numérique. Je veux trier le fichier par ce dernier champ numérique. Je ne peux pas faire:Bash: trier le fichier texte par la valeur du dernier champ

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

car le nombre de champs dans chaque ligne n'est pas constant. Je pense que sed, awk peut-être la réponse, mais je ne sais pas comment. E.g:

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

me donne la dernière valeur de la colonne, mais comment utiliser cela pour trier le fichier? Peut-être inverser les champs de chaque ligne dans le fichier avant le tri?

Répondre

27

Utilisez awk pour placer la touche numérique à l'avant. $NF est le dernier champ de l'enregistrement en cours. Trier. Utilisez sed pour supprimer la clé en double.

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

pas besoin de redirection. 'awk -F, '{print $ NF, $ 0}' votre fichier ' – ghostdog74

0

Quelque chose comme

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

devrait le faire, aussi longtemps que des virgules ne sont jamais cités en aucune façon. S'il s'agit d'un fichier CSV à part entière (dans lequel les virgules peuvent être cotées avec une barre oblique inverse ou un espace), vous avez besoin d'un véritable analyseur CSV.

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

Pourquoi ne pas utiliser 'ex' si vous allez aller dans cette voie? Vim obtient cette fonctionnalité particulière de 'ex' de toute façon. –

+0

'ex' est juste' vim', avec l'option '-e'. Ça n'a pas vraiment d'importance dans ce cas. – Benoit

+0

'ex' est antérieur à' vim' (et 'vi') assez longtemps. 'vim' peut avoir un mode d'émulation' ex', mais cela ne le rend pas 'ex'. –

0

Perl one-liner:

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

Je vais moi jeter ici comme une alternative (et je ne pouvais pas travailler awk) :)

exemple de fichier :

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

Code:

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])))" 
Questions connexes