@sortedip = map {
"$$_[0].$$_[1].$$_[2]$$_[3]"
} sort {
($$a[0] <=> $$b[0]) or
($$a[1] <=> $$b[1]) or
($$a[2] <=> $$b[2]) or
($$a[3] <=> $$b[3])
} map {
/(\d+)[.](\d+)[.](\d+)[.](\d+)/;
[$1, $2, $3, $4]
} @ip;
Personally I would leave off that (typographically)
first map, so that you get a list of arrayrefs; the range
checking will probably be easier that way. Speaking
of the range checking... you probably want to use a
foreach loop over the now sorted list, in each case
keeping track of the previous IP or range and pushing
that if the current IP isn't contiguous. Something
along these lines...
@sorted = sort {
($$a[0] <=> $$b[0]) or
($$a[1] <=> $$b[1]) or
($$a[2] <=> $$b[2]) or
($$a[3] <=> $$b[3])
} map {
/(\d+)[.](\d+)[.](\d+)[.](\d+)/;
[$1, $2, $3, $4]
} @ip;
my $previous = []; my @range = ();
for $current (@sorted, [260, 0, 0, 0]) {
if (greaterbyone($previous,$current) {
$$previous[4] = $$current[3];
} else {
push @range, $previous;
$previous = $current;
}
greaterbyone just has to return true if the IP address
in its second argument is one greater than the IP
address or range in its first argument. I'll leave
that part as an exercise.
$;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}}
split//,".rekcah lreP rehtona tsuJ";$\=$ ;->();print$/
|