jbsu32
jbsu32

Reputation: 1064

Bash:: How to sort according to first numeric column of file?

4 lists are given like this. I need to sort them according to the first numerical column. Columns are seperated by tabs / \t.

France \t Paris \t 13.2 \t 14.2
Germany \t Munich \t Hamburg \t 16.9 \t 16.6
Norway \t 8.9 \t 9.1
Spain \t Barcelona \t Madrid \t Malaga \t 21.2 \t 19.4 

After sorting, these columns will look like ->

Norway \t 8.9 \t 9.1
France \t Paris \t 13.2 \t 14.2
Germany \t Munich \t Hamburg \t 16.9 \t 16.6
Spain \t Barcelona \t Madrid \t Malaga \t 21.2 \t 19.4 

They are sorted according to 8.9, 13.2, 16.9 & 21.2.

I have tried with something like sort -k 2n or sort -k 3n, which sorts the lists according to the 2nd or the 3rd column. But, 8.9, 13.2, 16.9 & 21.2 are located in the 2nd, 3rd, 4th & 5th column in the lists. How can I solve this??

Upvotes: 0

Views: 1199

Answers (4)

James Brown
James Brown

Reputation: 37394

In Gnu awk:

$ awk '{a[$0]=$(NF-1)} END {PROCINFO["sorted_in"]="@val_num_asc"; for(i in a) print i}' tst
Norway  8.9     9.1
France  Paris   13.2    14.2
Germany Munich  Hamburg 16.9    16.6
Spain   Barcelona       Madrid  Malaga  21.2    19.4

Downside: it removes duplicate rows.

Upvotes: 2

P....
P....

Reputation: 18351

This will sort based on penultimate column, it will extract and prepend the penultimate column at the start of each line and then applied numeric sort over it. Then earlier pre-pended column would be removed. This will also work with duplicate records.

awk '{print $(NF-1),$0}' inputfile| sort -n | cut -f2- -d' '
Norway    8.9    9.1
France    Paris    13.2    14.2
Germany    Munich    Hamburg    16.9    16.6
Spain    Barcelona    Madrid    Malaga    21.2    19.4

Upvotes: 0

redneb
redneb

Reputation: 23850

How about this:

sed -e 's/^[^0-9.]*\([0-9.]\+\).*$/\1\t\0/' input | sort -n | cut -f 2-

We extract the first numeric field and we insert it to the beginning of each line. Then we sort numerically all lines and then we remove the stuff that we added in the first step.

Upvotes: 6

Sundeep
Sundeep

Reputation: 23667

I have removed \t from input file for clarity, solution doesn't depend on spacing

$ cat ip.txt 
France  Paris  13.2  14.2
Germany  Munich  Hamburg  16.9  16.6
Norway  8.9  9.1
Spain  Barcelona  Madrid  Malaga  21.2  19.4 

$ perl -lne '($k)=/([\d.]+)/; $h{$k}=$_; END{print $h{$_} foreach (sort {$a <=> $b} keys %h)}' ip.txt 
Norway  8.9  9.1
France  Paris  13.2  14.2
Germany  Munich  Hamburg  16.9  16.6
Spain  Barcelona  Madrid  Malaga  21.2  19.4 
  • The first number (including decimal point) is used as key to save input lines in a hash variable
  • After all lines are read, the keys are sorted numerically and corresponding hash values printed out

Upvotes: 1

Related Questions