Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Okay, I've searched more than once for a script that sorts ip addresses from a text file (one address per line), my eyes are burning. Output to stdout is fine. Someone please toss me a bone, complete from #!/usr/bin/perl. I thank you. My burning eyes thank you. :) Jim Edwards

Replies are listed 'Best First'.
Re: ip sorting
by Zaxo (Archbishop) on Mar 20, 2003 at 23:11 UTC

    Ok, but I'd like to see what your try was (untested code follows).

    #!/usr/bin/perl use warnings; use strict; use Socket qw( inet_aton inet_ntoa); # takes file paths as argument for (@ARGV) { local $, = $/; open my $fh, '<', $_ or die $!; print map { inet_ntoa($_) } sort { $a <=> $b } map { chomp; inet_aton($_) } <$fh>; print $/; close $fh or die $!; }
    That will need perl 5.6+ to handle lexical filehandles and 3-arg open. Minor adjustment to run on older versions.

    Update: pg++, thanks for catching my error. I'll leave this as it is, see pg's reply below.

    After Compline,
    Zaxo

      This solution is actually on the right track.

      The only mistake is that the author thought the result from inet_aton is a number, but it is not. In fact, the result returned is a string.

      Simply modify that sort statement to:
      sort {$a cmp $b}
      Now this piece of code works properly (I tested the modified version).

      If you are interested in details, inet_aton converts ascii address into a c structure in_addr, i.e.
      struct in_addr { union { struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b; struct { u_short s_w1,s_w2; } S_un_w; u_long S_addr; } S_un; }
      ,which Perl interprets as a string, not an unsigned long.

      My testing code:
      use strict; use Socket qw( inet_aton inet_ntoa); local $, = $/; print map { inet_ntoa($_) } sort { $a cmp $b } map { chomp; inet_aton($_) } <DATA>; print $/; __DATA__ 128.1.1.0 127 23.4.5.6 255.255.255.255 45.27.128.0 localhost
        I had asked the original question regarding ip sorting. I
        had to come back in here because I'd said that the man -g
        worked fine. However, the list I'd tested it on wasn't
        long enough for a real test. It does not work.

        However pg's slight modification to Zaxo's original code
        did the trick. Thanks very much.

        My apologies for duplicating a thread. I've not been here before.

        Thanks everyone!

      I'm not a perl programmer, and my example would cause laughter for everyone else and embarrassment for me. :)

      Here's the output from the untested code:

      Argument "BmM-oM-5" isn't numeric in sort at /usr/bin/ipsort line 13, <$fh> line 12.
      Argument "CM-c\ng" isn't numeric in sort at /usr/bin/ipsort line 13, <$fh> line 12.
      Argument "M-Q\nM-Ri" isn't numeric in sort at /usr/bin/ipsort line 13, <$fh> line 12.
      Argument "M-QC^CM-B" isn't numeric in sort at /usr/bin/ipsort line 13, <$fh> line 12.
      Argument "BM-o^CI" isn't numeric in sort at /usr/bin/ipsort line 13, <$fh> line 12.
      Argument "M-QC\0M-2" isn't numeric in sort at /usr/bin/ipsort line 13, <$fh> line 12.
      Argument "M-Q\nM-Ri" isn't numeric in sort at /usr/bin/ipsort line 13, <$fh> line 12.
      Argument "M-QC^CM-L" isn't numeric in sort at /usr/bin/ipsort line 13, <$fh> line 12.
      Argument "M-OM-^\M-X$" isn't numeric in sort at /usr/bin/ipsort line 13, <$fh> line 12.
      Argument "D>Ge" isn't numeric in sort at /usr/bin/ipsort line 13, <$fh> line 12.
      Argument "E^AM-BJ" isn't numeric in sort at /usr/bin/ipsort line 13, <$fh> line 12.
      Argument "M-X^OM-\fM-^E" isn't numeric in sort at /usr/bin/ipsort line 13, <$fh> line 12.
      66.109.239.181
      67.227.10.103
      209.10.210.105
      209.67.3.194
      66.239.3.73
      209.67.0.178
      209.10.210.105
      209.67.3.204
      207.156.216.36
      68.62.71.101
      69.1.194.74
      216.15.140.133

      Thanks for everyone's time.

Re: ip sorting (naturally)
by tye (Sage) on Mar 21, 2003 at 07:30 UTC

    A "natural sort" should fit this bill, so click that link to find several versions (including some rather simple and quite fast implementations).

                    - tye
Re: ip sorting
by MrYoya (Monk) on Mar 20, 2003 at 23:25 UTC
Re: ip sorting
by fokat (Deacon) on Mar 21, 2003 at 15:53 UTC

    Since TIMTOWTDI, you can also do this (slightly tested code)..

    #!/usr/bin/perl use strict; use warnings; use NetAddr::IP; # Beware large IP sets... print join("\n", map { $_->addr } sort map { new NetAddr::IP $_ } <DAT +A>), "\n"; __DATA__ 10.1.5.2 10.1.1.2 10.1.0.1 10.1.1.0 10.1.1.1 10.1.5.1

    Best regards

    -lem, but some call me fokat

Re: ip sorting
by Anonymous Monk on Mar 20, 2003 at 22:57 UTC
    man cut
Re: ip sorting
by Anonymous Monk on Mar 20, 2003 at 23:00 UTC
    and man sort
      sort -g does the job fine. I thought surely I looked at that
      and it didn't work for me. I'm not so lazy that I
      can't read a man page, I just overlooked this.

      Thanks