I have a text file containing ~300k rows. Each row has a varying number of comma-delimited fields, the last of which is guaranteed numerical. I want to sort the file by this last numerical field. I can't do:

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

as the number of fields in each row is not constant. I think sed, awk maybe the answer, but not sure how. E.g:

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

gives me the last column value, but how to use this to sort the file?


Use awk to put the numeric key up front. $NF is the last field of the current record. Sort. Use sed to remove the duplicate key.

awk -F, '{ print $NF, $0 }' yourfile | sort -n -k1 | sed 's/^[0-9][0-9]* //'
vim file.in -c '%sort n /.*,\zs/' -c 'saveas file.out' -c 'q'
  • 1
    Why not use ex if you're going to go that route? Vim gets that particular functionality from ex anyway. – JUST MY correct OPINION Sep 30 '10 at 15:40
  • ex is just vim, with the -e option. Does not really matter in this case. – Benoit Sep 30 '10 at 15:50
  • ex predates vim (and vi) by quite a long time. vim may have an ex emulation mode, but this does not make it ex. – JUST MY correct OPINION Oct 1 '10 at 2:48
  • Yes. But if you have vim on your system, ex will be a symlink to vim usually. Vim detects at startup what name it has been invoked under. – Benoit Oct 1 '10 at 15:11

Maybe reverse the fields of each line in the file before sorting? Something like

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

should do it, as long as commas are never quoted in any way. If this is a full-fledged CSV file (in which commas can be quoted with backslash or space) then you need a real CSV parser.


Perl one-liner:


I'm going to throw mine in here as an alternative (and I couldn't get awk to work) :)

sample file:

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


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

Python one-liner:

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

Your Answer

