Sorting file by a field, and then by another field.

Hi all,
Sorry the title is a mess, but did not find a better description at the time.
So here is my problem:
I have an input file:

8:Mass40s --        0
48:Mass40s --        0
67:Mass40s --        0
86:Mass40s --        0
105:Mass40s --        0
9:Mass --        1
49:Mass --       86
68:Mass --       78
87:Mass --        0
106:Mass --        0
10:Mass Promo --      324
50:Mass Promo --     1077
69:Mass Promo --      871
88:Mass Promo --        0
107:Mass Promo --       19

How can I sort it first by name and then by number (like one does in excel for example).
I tried with

sort -t : -k2,1 input_file

and other combinations (k1,2;k2,2...etc) but it sorts either the first field (numeric) or the second one.

Note: I know the input file is exactly like I�m asking it to be, but this is a very small part of the input file where all the data are scrambled. So please take this in account.

Also if I have a input file like:

10:Mass Promo --      324
50:Mass Promo --     1077
69:Mass Promo --      871
88:Mass Promo --        0
107:Mass Promo --       19
10:Mass Promo --      299
50:Mass Promo --     1008
69:Mass Promo --      733
88:Mass Promo --        0
107:Mass Promo --       29

Why the sort -n input_file command sorts by number and produce an output (for example):

10:Mass Promo --      299
10:Mass Promo --      324
50:Mass Promo --     1008
50:Mass Promo --     1077
69:Mass Promo --      733
69:Mass Promo --      871
88:Mass Promo --        0
88:Mass Promo --        0
107:Mass Promo --       19
107:Mass Promo --       29

If you notice, you can see that it sorts by the first field and the third also, and I don't want that, I just one the first field sorted so that the upper line stays on top and not on below or bottom according to its value.

For this I tried

sort -n -t : k1,1 input_file

and

sort -t : k1,1 -n input_file

but none of them work.

So I hope you guys can shed some light on this issue as I need to make this easy to read and copy for my weekly reports.

I�m open to any suggestions whether in sort or awk commands.

Thanks and I hope I was clear enough.

Hi, for your first question it depends on whether the numbers in the last column are part of the description. If they are this should work:

sort -t: -k2 -k1n infile

otherwise you would need something like this:

sed 's/:/ /' infile | sort -k2,3 -k1n |sed 's/ /:/' infile

For the second question that needs the original value intact for the other fields, this is called a stable sort. For GNU sort the option is -s:

sort -sn infile

Is this what you are looking for: -

sed 's/:/ /' infile | sort -k2,3 -k1n | sed 's/\(^[0-9]*\) /\1:/'

Output: -

9:Mass --        1
49:Mass --       86
68:Mass --       78
87:Mass --        0
106:Mass --        0
8:Mass40s --        0
48:Mass40s --        0
67:Mass40s --        0
86:Mass40s --        0
105:Mass40s --        0
10:Mass Promo --      324
50:Mass Promo --     1077
69:Mass Promo --      871
88:Mass Promo --        0
107:Mass Promo --       19

Hi there,
Thanks for the answers provided, and it did helped me with the first question, so thanks Scrutinizer and Steadyonabix.
But for the second part of my questions, the stable sort option is an valid option on my server linux version, I think....
I tried:

sort -t: -k2 -k1n infile |sort -sn

and

sort -sn infile

But it does not sort the 1st field independently of the other....
If you know another way I would be grateful.
Anyway thanks for your help so far.

So you wanted to sort the first column independently:

cut -d: -f1 infile |sort -n |paste -d: - infile |sed 's/:[^:]*//'

gawk 'BEGIN{OFS=FS=":"}{a[NR]=$1;b[NR]=$2}END{asort(a);for(i=1;i in a;++i)print a,b}' infile

With regard to the stable sort the simplest approach is to append a numeric key for the sort then remove it: -

[[ -a tmpfile ]] && rm tmpfile 

nawk -F":" ' { print $0"|"++_[$1] >> "tmpfile" } ' infileb 

sort -t"|" -k1n -k2n tmpfile | cut -d"|" -f1 > outfile 

cat outfile

Output: -

10:Mass Promo --      324
10:Mass Promo --      299
50:Mass Promo --     1077
50:Mass Promo --     1008
69:Mass Promo --      871
69:Mass Promo --      733
88:Mass Promo --        0
88:Mass Promo --        0
107:Mass Promo --       19
107:Mass Promo --       29