LinuxQuestions.org
Support LQ: Use code LQCO20 and save 20% on CrossOver Office
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
LinkBack Search this Thread
Old 09-24-2007, 08:24 AM   #1
humbletech99
Member
 
Registered: Jun 2005
Posts: 374

Rep: Reputation: 30
Bash: sorting by two fields


I am using bash and need to sort a bunch of numbers that look like the following example:
Code:
9.1
9.2
...
9.N
10.1
10.2
...
10.N
I am having trouble because the sort command either sorts by one field or the other, so if I just | sort -n I end up with
Code:
9.1
9.20
9.21
...
9.2
9.30
9.31
...
9.3
...
10.1
10.20
10.21
...
10.2
Does anyone have a cunning way of sorting by field one and then subsorting by field 2 without losing the order of the first field? If I sort by field 2 then of course the 9 and 10 at the beginning would could out of order.
 
Old 09-24-2007, 08:36 AM   #2
druuna
LQ Veteran
 
Registered: Sep 2003
Location: the Netherlands
Distribution: lfs, debian, rhel
Posts: 7,514
Blog Entries: 1

Rep: Reputation: 1140Reputation: 1140Reputation: 1140Reputation: 1140Reputation: 1140Reputation: 1140Reputation: 1140Reputation: 1140Reputation: 1140
Hi,

Did you try the -g option instead of the -n option?

Man sort for the details.

Hope this helps.
 
Old 09-24-2007, 09:02 AM   #3
humbletech99
Member
 
Registered: Jun 2005
Posts: 374

Original Poster
Rep: Reputation: 30
yes of course I manned sort before posting and I tried -g as well at that time but it doesn't give the desired effect, the sort still comes out wrong with .11 before .2 for example, same as demonstrated above.
 
Old 09-24-2007, 09:15 AM   #4
druuna
LQ Veteran
 
Registered: Sep 2003
Location: the Netherlands
Distribution: lfs, debian, rhel
Posts: 7,514
Blog Entries: 1

Rep: Reputation: 1140Reputation: 1140Reputation: 1140Reputation: 1140Reputation: 1140Reputation: 1140Reputation: 1140Reputation: 1140Reputation: 1140
Unusefull (read: dumb) reply removed.

Last edited by druuna; 09-24-2007 at 09:30 AM. Reason: Totally misunderstood this one :-)
 
Old 09-24-2007, 09:24 AM   #5
matthewg42
Senior Member
 
Registered: Oct 2003
Location: UK
Distribution: Kubuntu (x86), Debian (PPC)
Posts: 3,528

Rep: Reputation: 60
Lightbulb

Well, you can do it with a short Perl program. Be aware that this will slurp up the whole input file into memory, so if it's a huge file, this is probably not a good method.

Code:
#!/usr/bin/perl
# save this into a file called "mysort" and make that executable
# then invoke "mysort" on your input file.  The sorted output will
# be printed on stdout, so you can re-direct it like this:
#
# mysort  input_file > output_file

sub my_cmp {
        @a=split(/\./, $a, 3);
        @b=split(/\./, $b, 3);

        if ($a[0] ne $b[0]) { return $a[0] <=> $b[0]; }
        else { return $a[1] <=> $b[1]; }
}

foreach (sort my_cmp <>) { print; }
 
Old 09-24-2007, 12:50 PM   #6
Hobbletoe
Member
 
Registered: Sep 2004
Location: Dayton, Oh
Distribution: Linux Mint 10, Linux Mint 11
Posts: 148

Rep: Reputation: 17
For just bash, you can try ...

Code:
#!/bin/bash

list=($(cat infile | awk -F . '{print $1}' | sort -ug))

for i in $(seq 0 $((${#list[*]}-1)))
do 
 ftemp=$(mktemp)
 egrep ^${list[${i}]}'\.' infile | awk -F . '{print $2}' >> ${ftemp}
 list2=($(sort -n ${ftemp}))
 for j in $(seq 0 $((${list2[*]}-1)))
 do
  echo ${list[${i}]}.${list2[${j}]}
 done
 rm ${ftemp}
done
Basically, what I've done is to sort the first field (list), then create a temporary file that contains only the second field for each list, and I sort that out into a second list (list2). Then it is a simple matter of echoing out the first field . second field. Then get rid of the temporary file at the end of each first field, though I suppose you could skip that if you want. This works if you have something like 1 and 10 in the same file as well (set my test data up to make sure).

Hobbletoe Clubfoot
 
Old 09-25-2007, 01:29 PM   #7
LasseW
Member
 
Registered: Oct 2004
Distribution: Fedora 7, OpenSuse 10.2
Posts: 108

Rep: Reputation: 15
Assuming the numbers are in file.dat:

$ awk -F. '{print $1,$2}' file.dat|sort -nk1 -nk2|sed 's/ /./'
9.1
9.2
9.3
9.11
9.20
9.21
9.30
9.31
10.1
10.2
10.11
10.20
10.21
 
Old 09-25-2007, 03:30 PM   #8
makyo
Member
 
Registered: Aug 2006
Location: Saint Paul, MN, USA
Distribution: {Free,Open}BSD, CentOS, Debian, Fedora, Solaris, SuSE
Posts: 706

Rep: Reputation: 68
Hi.

See http://forums.debian.net/viewtopic.php?t=19478 ... cheers, makyo
 
  


Reply

Tags
numeric, sort, version


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
bash, sorting mp3's, problem in "for" ... may be zomane Programming 3 10-06-2006 07:08 AM
Sorting files in BASH deleted/ Linux - Newbie 16 01-26-2006 06:03 AM
Two New LQ Profile Fields jeremy LQ Suggestions & Feedback 8 07-12-2005 11:10 PM
inittab fields env Linux - General 2 03-04-2005 12:36 PM
compulsory fields masand LQ Suggestions & Feedback 20 09-07-2004 04:33 PM


All times are GMT -5. The time now is 11:17 AM.

Main Menu
 
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: @linuxquestions
Open Source Consulting | Domain Registration