LinuxQuestions.org
Help answer threads with 0 replies.
Home Forums Tutorials Articles Register
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
  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
Posts: 10,532
Blog Entries: 7

Rep: Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405
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
Posts: 10,532
Blog Entries: 7

Rep: Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405Reputation: 2405
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 12.10 (using awesome wm though)
Posts: 3,530

Rep: Reputation: 65
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 17
Posts: 150

Rep: Reputation: 18
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: 735

Rep: Reputation: 76
Hi.

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


Reply

Tags
numeric, sort, version



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



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

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 03:16 PM.

Main Menu
Advertisement
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
Open Source Consulting | Domain Registration