35

I have this input:

sdkxyosl 1
safkls 2
asdf--asdfasxy_asd 5
dkd8k  jasd 29
sdi44sw 43
asasd afsdfs 10
rklyasd 4

I need this output:

sdi44sw 43
dkd8k  jasd 29
asasd afsdfs 10
asdf--asdfasxy_asd 5
rklyasd 4
safkls 2
sdkxyosl 1

So i need to sort the lines by the last column.

I don't know how many columns are in one line.

I just can't figure it out, how to do it. I don't have "perl powers". I just have ~average scripting powers with sed, awk, cut, etc..

Does somebody know how to do it?

2 Answers 2

55

The following command line uses awk to prepend the last field of each line of file.txt, does a reverse numerical sort, then uses cut to remove the added field:

awk '{print $NF,$0}' file.txt | sort -nr | cut -f2- -d' '
6
  • @forcefsck: I don't think it's possible with only sort -k. The begfield function in GNU sort just counts down to zero. Your decorate-sort-undecorate (DSU) approach seems to be the best way I think.
    – Mikel
    Commented Apr 2, 2011 at 23:20
  • Out of interest, why $NF,$RS and not $NF,$0? I didn't know $RS did that. (I guess it's equivalent to $NF,$"\n", which does the same, but that's also surprising I think.)
    – Mikel
    Commented Apr 3, 2011 at 0:36
  • 2
    @johnny8888, @forcefsck: In awk, $ can be followed by any expression. “The effect of the field number expression evaluating to anything other than a non-negative integer is unspecified”. GNU awk (on my system) treats a string like "\n" as zero. Others (e.g. the original implementation by A, W and K) abort with an error message. If RS happened to be a digit, you'd get the corresponding field on any implementation. So don't do this, use $0. Commented Apr 3, 2011 at 11:51
  • 2
    Really neat! So the long explanation of what is going on: with awk, print the last field first then the whole record, sort in reverse numerically, then trim off the first column using cut.
    – phyatt
    Commented Nov 7, 2016 at 15:00
  • 2
    The method used here is called Schwartzian transform.
    – Cyrus
    Commented Nov 23, 2021 at 20:48
1

Sort last column numerically descending with GNU awk:

awk '{
       # save current row in array with current row number as index
       row[NR]=$0

       # save current last field in array with current row number as index
       last[NR]=$NF
     }
     END{
       # sort array "last" numerically ("num") based on its
       # values ("val") descending ("desc")
       PROCINFO["sorted_in"]="@val_num_desc";

       for(i in last)
         print row[i]
     }' file

As one line:

awk '{ row[NR]=$0; last[NR]=$NF } END{ PROCINFO["sorted_in"]="@val_num_desc"; for(i in last) print row[i] }' file

Output:

hello my name is Jordan: 476 
hello my name is Manu: 98
hello my name is Joi: 45
hello my name is Loi:  23 
hello my name is John:  4

See 8.1.6 Using Predefined Array Scanning Orders with gawk for more sorting algorithms and 8 Powerful Awk Built-in Variables – FS, OFS, RS, ORS, NR, NF, FILENAME, FNR

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .