上篇提到纯真ip库有很多行是浪费的,比如下面这种:yaml 223.214.0.0 223.215.255.255 安徽省 电信 223.216.0.0 223.219.255.255 日本 223.220.0.0 223.220.162.1 青海省 电信 223.220.162.2 223.220.162.2 青海省海东地区 平安县九歌网吧 223.220.162.3 223.221.255.255 青海省 电信 很简单的223.220.0.0-223.221.255.255段,却被拆成了三行。于是在通过起始ip结束ip计算子网之前,还需要合并一下这些ip段。 因为涉及ip比对,所以第一反应想到了mysql里有的inet_aton函数,去CPAN上搜了一下,发现有NetAddr::IP::Util模块有inet_aton函数,结果一用,发现居然生成的不是数字……于是从网上找到了pack的办法,如下: ```perl#!/usr/bin/perl -w while(<>){ next unless $_ =~ /^(\S+)\s+(\S+)\s+(\S+)/; my $low = unpack(‘N’,(pack(‘C4’,(split( /./,$1))))); #下面这行是IP::QQWry模块里的写法

print $1 * 2563 + $2 * 2562 + $3 * 256 + $4 if $1 =~ /(\d+).(\d+).(\d+).(\d+)/;;

my $high = unpack('N',(pack('C4',(split( /\./,$2)))));
next if $low == $high;
my $addr = $3;
unless ( $hash->{$addr}->{high}->[0] ) {
    $hash->{$addr}->{low}->[0] = $low;
    $hash->{$addr}->{high}->[0] = $high;
    next;
}; #如果中间就隔几个ip的,可以无视之,合并就是了……
if ( $low - $hash->{$addr}->{high}->[0] < 16 ) {
    $hash->{$addr}->{high}->[0] = $high;
    next;
};
unshift @{$hash->{$addr}->{low}}, $low;
unshift @{$hash->{$addr}->{high}}, $high; }; foreach $addr ( keys %{$hash} ) {
my $i = 0;
while ( $hash->{$addr}->{low}->[$i] ) {
    print $addr . "\t" . &nota($hash->{$addr}->{low}->[$i]) . "\t" . &nota($hash->{$addr}->{high}->[$i]) , "\n";
    $i++;
} }; sub nota {
my $aton = shift;
@a = unpack('C4',(pack('N',$aton)));
return (join "\.",@a); };``` pack真复杂,基本看不懂perldoc,唉……

最后汇报一下运行结果: 合并前一共428452行,合并后103008行。