The macosxhints Forums

The macosxhints Forums (http://hintsforums.macworld.com/index.php)
-   Applications (http://hintsforums.macworld.com/forumdisplay.php?f=5)
-   -   Sort App (word, excell) or Unix or..... (http://hintsforums.macworld.com/showthread.php?t=21839)

anthlover 03-18-2004 05:21 PM

Sort App (word, excell) or Unix or.....
 
I maintain a number of host tables that are Vi edited.

A number of them are unruly and need to be sorted by IP. Every method I have tried does not work with IPS I am trying to sort.

The Sort commands all seem to ignore anything that comes after the periods in IP Addresses.

e.g. 204.80.70 seems just fine to sort coming after 204.6.80.200?

Any suggestions for app or methodology or command that likes ips or Decimals.

At the moment I am brute forcing as the tables are about 85 percent sorted anyway.

Thnax in advance.

huskerchad 03-18-2004 07:44 PM

An awk wizard can probably help you with this. You might want to post in the unix forum in case none of them see it here.

vancenase 03-18-2004 08:36 PM

the unix command 'sort' seems do this ... if you can't get it to work, maybe use 'man sort' and find a switch that might help

Code:

[v:~] v% cat t
1.0.0.3
1.0.0.1
1.2.1.1
1.0.0.2

[v:~] v% sort t
1.0.0.1
1.0.0.2
1.0.0.3
1.2.1.1


stetner 03-18-2004 08:47 PM

I assume you want this:
Code:

1.1.1.1
1.2.3.4
1.10.4.4
1.20.2.3

rather than this:
Code:

1.1.1.1
1.10.4.4
1.2.3.4
1.20.2.3

This chunk of perl should do it for you:
Code:

#! /usr/bin/perl
$"=" - ";
while(<>) {
        @x= split(/\./,$_);
        @y= (@y,sprintf("%b %b %b %b", @x));
}

@y=sort( @y);

for ( $i = 0; $i <@y; $i++ ) {
    $a = $y[$i];
    ($a1, $a2, $a3, $a4)=split(/ /,$a);
      printf("%d\.%d\.%d\.%d\n",bin2dec($a1),bin2dec($a2),bin2dec($a3),bin2dec($a4));
}

sub dec2bin {
    my $str = unpack("B32", pack("N", shift));
    $str =~ s/^0+(?=\d)//;  # otherwise you'll get leading zeros
    return $str;
}

sub bin2dec {
    return unpack("N", pack("B32", substr("0" x 32 . shift, -32)));
}


vancenase 03-18-2004 08:56 PM

although i'm not sure it's technically correct, this command gives the same output as above
Code:

sort -t . -n +1 filename
i though i would have to add an '+2 +3 +4' for proper usage (sort each column; after the +1), but it works with the +1

anthlover 03-18-2004 09:54 PM

Thanx
 
I will try....

If I were to use thee non Perl are you saying to do

sort -t . -n +1 +2+3+4 filename

or

sort -t . -n +1
sort -t . -n +2
sort -t . -n +3
sort -t . -n +4

I would think the latter would mess up the sequence.

If it makes a difference were talking about 20 Subnets within one file.

vancenase 03-18-2004 09:57 PM

this seemed to work,
Code:

sort -t . -n +1 filename
but i thought it would have to be
Code:

sort -t . -n +1 +2 +3 +4 filename
(not the commands on separate lines) ... but maybe the 'sort' program doesn't work like that

try the first line above, if it doesn't work, the second ... if not ... the perl code should work!

anthlover 03-18-2004 10:00 PM

ok with spaces:)
 
I'll try

vancenase 03-18-2004 10:22 PM

just use the first one, here is an excerpt from 'man sort'

Quote:

+POS1 [-POS2]
Specify a field within each line to use as a sorting key. The
field consists of the portion of the line starting at POS1 and
up to (but not including) POS2 (or to the end of the line if
POS2 is not given). The fields and character positions are num-
bered starting with 0.
so apparently +1 goes from the first field to the end ...
good code:
Code:

sort -t . -n +1 filename

stetner 03-18-2004 10:56 PM

Argh, my code is wrong too. But the sort answer does not work either. A good data set is
Code:

1.1.1.1
2.1.1.1
10.1.1.1
2.2.2.2
2.3.2.2
2.20.2.2
3.3.3.3
3.3.4.3
3.3.30.3
4.4.4.4
4.4.4.5
4.4.4.40

The sort above gives:
Code:

$ sort -t . -n +1 x
1.1.1.1
10.1.1.1
2.1.1.1
2.2.2.2
2.3.2.2
3.3.3.3
3.3.30.3
3.3.4.3
4.4.4.4
4.4.4.40
4.4.4.5
2.20.2.2

and my (broken) code gives:
Code:

$ ipsort x
1.1.1.1
2.1.1.1
2.2.2.2
2.20.2.2
2.3.2.2
4.4.4.4
4.4.4.5
4.4.4.40
10.1.1.1
3.3.4.3
3.3.3.3
3.3.30.3

Close, but no cigar. Stay tuned for a fixed version.

stetner 03-18-2004 11:00 PM

This has it:
Code:

#! /usr/bin/perl
while(<>) {
        @x= split(/\./,$_);
        @y= (@y,sprintf("%08b %08b %08b %08b", @x));
}

@y=sort( @y);

for ( $i = 0; $i <@y; $i++ ) {
    $a = $y[$i];
    ($a1, $a2, $a3, $a4)=split(/ /,$a);
      printf("%d\.%d\.%d\.%d\n",bin2dec($a1),bin2dec($a2),bin2dec($a3),bin2dec($a4));
}

sub bin2dec {
    return unpack("N", pack("B32", substr("0" x 32 . shift, -32)));
}

Which given the above data does this:
Code:

1.1.1.1
2.1.1.1
2.2.2.2
2.3.2.2
2.20.2.2
3.3.3.3
3.3.4.3
3.3.30.3
4.4.4.4
4.4.4.5
4.4.4.40
10.1.1.1


vancenase 03-18-2004 11:04 PM

ah ha! try this one, found it using google:
Code:

  file
    (IPv4 hosts database), sorted by the numeric IP address (the
    first four numeric fields):

    example$ sort -t . -k 1,1n -k 2,2n -k 3,3n -k 4,4n /etc/hosts
    example$ sort -t . +0 -1n +1 -2n +2 -3n +3 -4n /etc/hosts


anthlover 03-18-2004 11:16 PM

Thanx
 
Host table is @ work so to it in the am.

Thanx two you do I have 3 ways again:)

On the non Perl any Idea of advantage of one of the other:

example$ sort -t . -k 1,1n -k 2,2n -k 3,3n -k 4,4n /etc/hosts
example$ sort -t . +0 -1n +1 -2n +2 -3n +3 -4n /etc/hosts

anthlover 03-19-2004 12:42 AM

Forgot I had emailed myself one of the host tables
 
The command runs but does not sort properly, weird.

example$ sort -t . -k 1,1n -k 2,2n -k 3,3n -k 4,4n /etc/hosts
example$ sort -t . +0 -1n +1 -2n +2 -3n +3 -4n /etc/host

Off to Perl

:) :) I lied it worked fine.******** Thanx

anthlover 03-19-2004 12:47 AM

Stenter I do not know Perl
 
In your example where is the file name dir/path info?

Did I miss it?

Can I just run it from Terminal?

And can I save the output from there?

stetner 03-19-2004 01:10 AM

Ahh, I got so caught up in sorting IPs that I forgot it is a hosts file you are working on. Give me a minute....

stetner 03-19-2004 01:44 AM

OK, here you go. It assumes lines are of the form "IPaddress name(s)" and discards other lines (ie comments)

Simply put this into a file, 'chmod 755 filename' and runit either as:
./filename /path/to/hosts >/path/to/OUTPUTFILE
or
./filename </path/to/hosts >/path/to/OUTPUTFILE

I am just starting to use perl, I am a sed/awk/sh type myself, so there are probably better ways of doing this...
Code:

#! /usr/bin/perl
while(<>) {
chomp;
    if( m/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}.*/ ) {
        ($IP, $rest) = split(/[^.\d]/,$_, 2);
        @IP2 = split( /\./,$IP);
        @IP3 = (@IP3,sprintf("%08b %08b %08b %08b %s", @IP2, $rest ));
    }
}

@IP3=sort( @IP3);

for ( $i = 0; $i <@IP3; $i++ ) {
    $a = $IP3[$i];
    ($a1, $a2, $a3, $a4, $a5)=split(/ /,$a,5);
      printf("%d\.%d\.%d\.%d %s\n",bin2dec($a1),bin2dec($a2),bin2dec($a3),bin2dec($a4), $a5 );
}

sub bin2dec {
    return unpack("N", pack("B32", substr("0" x 32 . shift, -32)));
}


vancenase 03-19-2004 07:35 AM

Re: Stenter I do not know Perl
 
Quote:

Originally posted by anthlover
In your example where is the file name dir/path info?

Did I miss it?

Can I just run it from Terminal?

And can I save the output from there?
to save output from running these commands in the terminal do the following (if you have not already):
Code:

example$ sort -t . -k 1,1n -k 2,2n -k 3,3n -k 4,4n /etc/hosts > /path/to/file/to/save
example$ sort -t . +0 -1n +1 -2n +2 -3n +3 -4n /etc/host > /path/to/new/file/to/save

others can give the etiquette on when to use > vs. >| (i can't remember and i've got to go to work!)

anthlover 03-19-2004 05:15 PM

I ended up just saving as from Terminal window:)
 
And thank you both for all your hard work.
It is neat to have the syntex to auto output it to a file.

I have not had a chance ot try Stenter's Perl yet.

Even with Ips Sorted it took 8 hours straight to clean up that 30 Page host table, Phew.

I Ended up Adding Every "unused" IP from Every segment that was missing and listing each as "Open" or "In Use?" (Scummed/not Documented).

Now we can decide how many more VLans we need for our new sytstems. And at the same time play detective on the "In Use?" (Scummed/not Documented). ones.

stetner 03-19-2004 06:10 PM

Yeah, been there done that....

Best to keep a DB with allocated IPs and only allow allocated IPs on the network. People think I am a network nazi, but you only have to go through what you did once or twice before you decide to get tough! :)

anthlover 03-19-2004 06:49 PM

Yeah in my home I go the next level MAC Address verification on who can be on the net
 
Unfortunately @ work I am the Systems Manager of Chain of Hospitals Radiology Departments not the Network Manager and to boot this group is Radioloy, not IT.

Even if they were willing to not route IPS that we have not "accounted" for It would be too cubersome. It is difficult enough to get connections Punched and trouble shoot net problems that arrise in our extensive sites.

It is tempting though:)


All times are GMT -5. The time now is 04:05 PM.

Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2014, vBulletin Solutions, Inc.
Site design © IDG Consumer & SMB; individuals retain copyright of their postings
but consent to the possible use of their material in other areas of IDG Consumer & SMB.