Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在perl中查找子网中的所有IP_Perl_Ip Address - Fatal编程技术网

在perl中查找子网中的所有IP

在perl中查找子网中的所有IP,perl,ip-address,Perl,Ip Address,我有一个带有子网掩码的IP,希望创建一个表,其中每一行都是一个IP 有点像这样: IP | MAC | Alive 192.168.1.1 | ... | yes 192.168.1.2 | ... | no 192.168.1.3 | ... | yes ... 对于子网为/24的范围,这很容易,因为我可以生成从0到254的For循环,但生成子网为/21的表时遇到问题。有没有办法在perl中找到最小主机、最大主机以及两者之间的所有内容 我已经检查了Net::IP和

我有一个带有子网掩码的IP,希望创建一个表,其中每一行都是一个IP

有点像这样:

IP          | MAC  | Alive 
192.168.1.1 | ...  | yes
192.168.1.2 | ...  | no
192.168.1.3 | ...  | yes
...
对于子网为/24的范围,这很容易,因为我可以生成从0到254的For循环,但生成子网为/21的表时遇到问题。有没有办法在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。我创建了一个助手子系统,它使用单例创建迭代器。您从子网传入任何IP,它将为您提供一个代码引用,您可以使用该代码引用来接收下一个IP地址对象。它将执行此操作,直到范围耗尽,此时返回
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\u ip\u迭代器
子系统中是词法的,因此您可以多次调用它,并为同时使用的不同子网返回不同的迭代器


当然,您可以只使用
while
循环和一个计数器变量来实现它,因为
nth()
在子网外使用索引调用它时将返回
undef
,但此解决方案更具可移植性。

Net::IP
的文档在本节中提供了一个如何执行此操作的示例

演示:

如果您只有所需范围内的IP,而没有前缀,则可以根据地址和网络掩码计算前缀。尝试类似的方法(可能有一种更聪明的方法可以通过
Net::IP
实现这一点,但我无法做到):


我也发现了这一点并尝试过,但它只适用于我使用子网地址的情况。看来我需要知道,不能使用第一个地址。因此它适用于
192.168.0.0/21
192.168.0/21
,但不适用于
192.168.0.1/21
。后者将在实例化时返回
unde
。添加了从范围内的任何地址获取此子网地址的方法。虽然不太好看,但我有点期待有一个函数能做到这一点,但却找不到它……关于执行时间的重要注意事项:使用模块
NETAddr::IP
nth方法
比使用
Net::IP
和循环快10倍左右,在相同的CIDR范围192.0.0/24下进行测试。我还在Bash中使用
nmap
:在很远的地方,时间单位是小时。
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
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);