在perl中查找子网中的所有IP
Find all IPs from subnet in perl
我有一个带子网掩码的 IP,我想创建一个 table,其中每一行都是一个 IP。
有点像这样:
IP | MAC | Alive
192.168.1.1 | ... | yes
192.168.1.2 | ... | no
192.168.1.3 | ... | yes
...
对于子网为 /24 的范围,这很容易,因为我可以生成一个从 0 到 254 的 for 循环,但是我在使用 /21 子网生成 table 时遇到了问题。有没有办法在 perl 中找到最小主机、最大主机以及介于两者之间的所有内容?
我已经检查了 Net::IP
和 NetAddr::IP
模块,但似乎无法解决我的问题。但是,我是一个 perl 新手,所以可能是我忽略了它。
编辑:
找到了如何查找第一个和最后一个地址:
my $range = "IP/subnet" ;
my $ip = new Net::IP ($range) || die;
print $ip->ip (), "\n";
print $ip->last_ip (), "\n";
现在我需要找到两者之间的 IP
你可以用 NetAddr::IP and the nth
method 做到这一点。我创建了一个 helper sub,它使用单例来创建迭代器。您从子网传入任何 IP,它会为您提供一个代码参考,您可以使用它来接收下一个 IP 地址对象。它将这样做直到范围用尽,此时它 returns undef
.
use strict;
use warnings 'all';
use NetAddr::IP;
use feature 'say';
sub make_ip_iterator {
my $ip = shift;
my $mask = NetAddr::IP->new($ip);
my $i = 0;
return sub {
return $mask->nth($i++);
}
}
my $iterator = make_ip_iterator('192.168.1.1/21');
while (my $ip = $iterator->()) {
say $ip;
}
因为 $mask
和 $i
在 make_ip_iterator
sub 中是词法的,您可以多次调用它并为您同时使用的不同子网返回不同的迭代器。
你当然可以只用一个 while
循环和一个计数器变量来实现它,因为 nth()
将 return undef
当它被调用时使用索引之外的索引子网,但此解决方案更便携。
Net::IP
的文档在 looping 部分有一个如何执行此操作的示例。
演示:
use Net::IP;
my $ip = new Net::IP("192.168.42.16/28");
do {
print $ip->ip(), "\n";
} while (++$ip);
192.168.42.16
192.168.42.17
192.168.42.18
192.168.42.19
192.168.42.20
192.168.42.21
192.168.42.22
192.168.42.23
192.168.42.24
192.168.42.25
192.168.42.26
192.168.42.27
192.168.42.28
192.168.42.29
192.168.42.30
192.168.42.31
如果您只有所需范围内的 IP,而没有前缀,则可以根据地址和网络掩码计算前缀。尝试这样的事情(尽管 Net::IP
可能有一种更聪明的方法来实现这一点,但我无法理解):
use Net::IP;
my $addr = "192.168.42.23";
my $len = 28;
my $mid = new Net::IP($addr, 4);
my $mask = Net::IP::ip_get_mask($len, 4);
my $first = $mid->binip() & $mask;
my $ip = new Net::IP(Net::IP::ip_bintoip($first, 4)."/$len", 4);
do {
print $ip->ip(), "\n";
} while (++$ip);
我有一个带子网掩码的 IP,我想创建一个 table,其中每一行都是一个 IP。
有点像这样:
IP | MAC | Alive
192.168.1.1 | ... | yes
192.168.1.2 | ... | no
192.168.1.3 | ... | yes
...
对于子网为 /24 的范围,这很容易,因为我可以生成一个从 0 到 254 的 for 循环,但是我在使用 /21 子网生成 table 时遇到了问题。有没有办法在 perl 中找到最小主机、最大主机以及介于两者之间的所有内容?
我已经检查了 Net::IP
和 NetAddr::IP
模块,但似乎无法解决我的问题。但是,我是一个 perl 新手,所以可能是我忽略了它。
编辑: 找到了如何查找第一个和最后一个地址:
my $range = "IP/subnet" ;
my $ip = new Net::IP ($range) || die;
print $ip->ip (), "\n";
print $ip->last_ip (), "\n";
现在我需要找到两者之间的 IP
你可以用 NetAddr::IP and the nth
method 做到这一点。我创建了一个 helper sub,它使用单例来创建迭代器。您从子网传入任何 IP,它会为您提供一个代码参考,您可以使用它来接收下一个 IP 地址对象。它将这样做直到范围用尽,此时它 returns undef
.
use strict;
use warnings 'all';
use NetAddr::IP;
use feature 'say';
sub make_ip_iterator {
my $ip = shift;
my $mask = NetAddr::IP->new($ip);
my $i = 0;
return sub {
return $mask->nth($i++);
}
}
my $iterator = make_ip_iterator('192.168.1.1/21');
while (my $ip = $iterator->()) {
say $ip;
}
因为 $mask
和 $i
在 make_ip_iterator
sub 中是词法的,您可以多次调用它并为您同时使用的不同子网返回不同的迭代器。
你当然可以只用一个 while
循环和一个计数器变量来实现它,因为 nth()
将 return undef
当它被调用时使用索引之外的索引子网,但此解决方案更便携。
Net::IP
的文档在 looping 部分有一个如何执行此操作的示例。
演示:
use Net::IP;
my $ip = new Net::IP("192.168.42.16/28");
do {
print $ip->ip(), "\n";
} while (++$ip);
192.168.42.16
192.168.42.17
192.168.42.18
192.168.42.19
192.168.42.20
192.168.42.21
192.168.42.22
192.168.42.23
192.168.42.24
192.168.42.25
192.168.42.26
192.168.42.27
192.168.42.28
192.168.42.29
192.168.42.30
192.168.42.31
如果您只有所需范围内的 IP,而没有前缀,则可以根据地址和网络掩码计算前缀。尝试这样的事情(尽管 Net::IP
可能有一种更聪明的方法来实现这一点,但我无法理解):
use Net::IP;
my $addr = "192.168.42.23";
my $len = 28;
my $mid = new Net::IP($addr, 4);
my $mask = Net::IP::ip_get_mask($len, 4);
my $first = $mid->binip() & $mask;
my $ip = new Net::IP(Net::IP::ip_bintoip($first, 4)."/$len", 4);
do {
print $ip->ip(), "\n";
} while (++$ip);