How can I sort the list of IP addresses in Perl?

I have a bunch of IP addresses stored in an array, for example:

my @ip = qw(10.11.1.1 10.100.1.1 ...); 

How can I sort the addresses in ascending order? I tried a simple sort , but it certainly didn't work out.

+4
source share
8 answers

IPv4 addresses are just 32-bit numbers.

 use Socket qw( inet_aton ); my @sorted = map substr($_, 4), sort map inet_aton($_) . $_, @ips; 

or

 my @sorted = map substr($_, 4), sort map pack('C4a*', split(/\./), $_), @ips; 

The first also accepts domain names.

+11
source

I do not like any solution that suggests more what he needs. I used to be burned on such things with compact notation, and I think this problem becomes more severe when IPv6 becomes more common. I will just let Net :: IP understand:

 use 5.010; use Net::IP; my @ip = qw( 192.168.1.10 172.16.5.5 256.0.0.1 192.168.1/24 127.1 127.0.1 fd00:6587:52d7:f8f7:5a55:caff:fef5:af31 fd24:cd9b:f001:884c:5a55:caff:fef5:af31 ); my @sorted = map { $_->[0] } sort { $a->[1] <=> $b->[1] } map { [ $_, eval { Net::IP->new( $_ )->intip } ] } @ip; say join "\n", @sorted; 

This handles compact and range notations perfectly, and eval catches the wrong IP addresses. I do not need to consider IPv4 and IPv6 separately:

 256.0.0.1 127.0.1 127.1 172.16.5.5 192.168.1/24 192.168.1.10 fd00:6587:52d7:f8f7:5a55:caff:fef5:af31 fd24:cd9b:f001:884c:5a55:caff:fef5:af31 
+6
source

Only IPv4 addresses?

 my @ip = map $_->[0], sort { $a->[1] cmp $b->[1] } map [ $_, join '', map chr, split /\./, $_ ], qw( 10.1.2.3 172.20.1.2 192.168.1.2 ); 
+1
source
+1
source

I watched @ikegami's answer, which turned out to be flawless, but I had no idea why. So I took a couple of points to understand the mechanics behind this, and I want to share my notes for future links for less experienced Perl experts ...

In this example, I chose two very specific IP addresses, because when encoded as ASCII, they will look like ABCD and EFGH , as seen on the output of the print Dumper() .

The trick is to prefix each line of an IP address with 4 bytes containing its binary representation. Then the entries are sorted and finally the prefix is ​​deleted again, leaving a list of sorted IP addresses.

The internal works are described in the comments, it is best to read them in numbered order.

 #!/usr/bin/perl use warnings; use strict; use Data::Dumper; my @ips = qw( 69.70.71.72 65.66.67.68 ); print Dumper( map( pack( 'C4a*' , split( /\./ ) , $_ ) , @ips ) ); foreach my $ip ( map( # 5. For each IP address that was enriched with 32 bits representation .... substr( $_ , 4) , # 6. Snip off the first four bytes as this is just a binary representation of the string, used for sorting. sort( # 4. Sort will essentially work on the first 4 octets as these will represent the entire remainder of the string. map( # 1. For each IP address in @ARGV ... pack( 'C4a*' , # 3. Change ASCII encoded octets from the IP address into a 32 bit 'string' (that can be sorted) and append it with the original IP address string for later use. split( /\./ ), $_ ) , # 2. Split the IP address in separate octets @ips # 0. Unsorted list of IP addresses. ) ) ) ) { print "$ip\n"; } 

The output will look like this:

 $VAR1 = 'EFGH69.70.71.72'; $VAR2 = 'ABCD64.65.66.67'; 64.65.66.67 69.70.71.72 

If the first two lines are from print Dumper() , which indicate that the IP addresses have a 32-bit prefix for representing numeric IP addresses.

+1
source
 sort -n -t . -k 1,1 -k 2,2 -k 3,3 -k 4,4 filename or | to sort -n -t . -k 1,1 -k 2,2 -k 3,3 -k 4,4 

and you can change this ... -r :-)

+1
source

This should give you a good start:

 #!/usr/bin/perl use strict; use warnings; sub Compare { # TODO: Error checking my @a = split /\./, $a; my @b = split /\./, $b; # TODO: This might be cleaner as a loop return $a[0] <=> $b[0] || $a[1] <=> $b[1] || $a[2] <=> $b[2] || $a[3] <=> $b[3]; } my @ip = qw( 172.20.1.2 10.10.2.3 10.1.2.3 192.168.1.2 ); @ip = sort Compare @ip; print join("\n", @ip), "\n"; 
0
source

There is a module for sorting software version numbers . Maybe this will do what you want?

0
source

Source: https://habr.com/ru/post/920987/


All Articles