<?xml version="1.0" encoding="windows-1252"?>
<node id="628086" title="How to sort output?" created="2007-07-22 02:36:49" updated="2007-07-21 22:36:49">
<type id="115">
perlquestion</type>
<author id="627941">
dguntner</author>
<data>
<field name="doctext">
Well, I'm down to the nitty-gritty at last! :-)  The script to produce a list of hosts pinged is working, but I haven't got a clue as to how to sort the list by ping time.  Here's the script in its current form:&lt;p&gt;

&lt;code&gt;
#!/usr/bin/perl -w
#
# Ping a range of IP addresses, and list sorted by ping time.
#
# This uses the ICMP echo method instead of UDP echo, as
# some routers don't pass UDP echo.  Also, if the remote host
# doesn't have an appropriate service listening on the UDP
# echo port, it won't answer.
#
# D. Guntner, 21-July-2007
# Ver 1.0, 21-July-2007

use Net::Ping;
use Net::Netmask;

die "I need root privs to run, dude.\n" unless $&gt; == 0;

# Get the IP address(es)
my $netaddr = shift(@ARGV);
usage() unless $netaddr;   # Give usage message if no input

my $hostname = "";
my $block = new Net::Netmask($netaddr);
my @hosts = $block-&gt;enumerate();

my $p = Net::Ping-&gt;new("icmp");
$p-&gt;hires();   # Comment out this line if no Time::HiRes installed
               # (Or better yet, install Time::HiRes... :-) )

# Create our host list to sort from
open OF, "&gt;hostlist.txt" or die "Can't create hostlist.txt: $!";

select OF;
$|++;    # Unbuffer output file
select STDOUT;

print("Now scanning $netaddr, please wait....\n");

foreach $host (@hosts) {
  ($ret, $duration, $ip) = $p-&gt;ping($host, 5.5);
  if ($ret) {
    printf OF ("%s [ip: $ip] is alive  %.2f ms)\n", gethostbyip($host), 1000 * $duration);
  }
}
close OF;
$p-&gt;close();

print("Now sorting the list....\n");

open IF, "&lt;hostlist.txt" or die "Can't open hostlist.txt for input: $!";
my @data = &lt;IF&gt;;
close IF;

# Don't need the file anymore, so delete it
#if (unlink("hostlist.txt") &gt; 0) {
#  print("Couldn't remove hostlist.txt file for some reason....\n");
#}

my @sorted = map {s/(^|\D)0+(\d)(?=\t)/$1$2/g; $_}
             sort
             map {s/(\d+)(?=\t)/sprintf"%03.3d",$1/ge; $_}
             @data;

print(@sorted);
               

sub gethostbyip {
  use Socket;
  
  my $hostip = $_[0];
  my $iaddr = inet_aton($hostip);
  my $hostname = gethostbyaddr($iaddr, AF_INET);
  $hostname = $hostip unless defined $hostname;
  return $hostname;
}

sub usage {
  use File::Basename;
  
  my $progname = basename($0);
  
  print &lt;&lt;"EO_USAGE";
This script will ping scan a range if IP addresses, and return
a list sorted by ping time.  Give address in CIDR format.

   Usage:    $progname {IP/NETMASK}
   Example:  $progname 1.2.3.4/24

You *could* put in only a single IP address, but there wouldn't
be much point to that, now would there? :-)
EO_USAGE
  exit;
}
&lt;/code&gt;

The "my @sorted" section there I copied as a placeholder from another script that was in one of the messages here, so I'd know the basic formula/idea.  However, I don't know what that stuff should be changed to in order to get the sorting order I want.  (Oh yea, and the "if" that's checking on the unlink to get rid of the file isn't working, either - the file unlinks fine but I always get the message. *grin*)&lt;p&gt;

The script provides output in the format of:&lt;p&gt;

&lt;code&gt;
some.host.name [ip: 111.222.333.444] is alive  70.05 ms)
&lt;/code&gt;

What I need is to sort that output by that last value there - the latency time.  I don't suppose there's a sort wizard here, who can tell me what the sort in my script needs to be changed to, so that it works as needed? :-)&lt;p&gt;

         --Dave
</field>
</data>
</node>
