in reply to Unsorted IP Addr list to sorted IP list with ranges

The sorting part is easy:

@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$/