![将 IP 列表转换为最小 CIDR 表示形式](https://linux22.com/image/206621/%E5%B0%86%20IP%20%E5%88%97%E8%A1%A8%E8%BD%AC%E6%8D%A2%E4%B8%BA%E6%9C%80%E5%B0%8F%20CIDR%20%E8%A1%A8%E7%A4%BA%E5%BD%A2%E5%BC%8F.png)
我有一个 IP 地址列表,如下所示:
10.10.0.0
10.10.0.1
10.10.0.2
...
10.10.0.255
172.171.0.5
...
172.171.0.67
是否有工具可以获取此类列表并计算这些 IP 地址的最小 CIDR 表示形式?
例如,对于上面的例子,我想得到以下输出:
10.10.0.0/24
172.171.0.5/32
172.171.0.6/31
172.171.0.8/29
172.171.0.16/28
172.171.0.32/27
172.171.0.64/30
编辑:为了澄清起见,“最小 CIDR 表示”将是包含我的输入文件的所有 IP 地址的最小 CIDR IP 地址集。
答案1
使用内置的 python 模块IP地址由 @AB 建议评论建议这个邮政。
任何一个总结地址范围(有开始、结束)或折叠地址(带有列表)可以使用。
对于这种情况,后者更方便。
import sys
import ipaddress
data = open(sys.argv[1],'r').read().splitlines()
ips = [ipaddress.IPv4Address(line) for line in data]
print('\n'.join([ip.with_prefixlen for ip in ipaddress.collapse_addresses(ips)]))
用法和输出:
$ python3 cidr.py file
10.10.0.0/24
172.171.0.5/32
172.171.0.6/31
172.171.0.8/29
172.171.0.16/28
172.171.0.32/27
172.171.0.64/30
答案2
这实际上是我一段时间以来一直有兴趣解决的问题,您可以使用该ipaddress
模块来完成此操作,但是我的实现可能不必要地复杂,但它确实有效:
from ipaddress import IPv4Address, IPv6Address, IPv4Network, IPv6Network
addrs = ["10.10.0.0", "10.10.0.1", "10.10.0.2", "10.10.0.255", "172.171.0.5", "172.171.0.67"]
out = []
while True:
if len(addrs) == 0:
break
found = False
for index in out:
if IPv4Network(addrs[0], 32).subnet_of(index.supernet(new_prefix=8)):
cur = index
while True:
if cur.supernet_of(IPv4Network(addrs[0], 32)):
break
else:
cur = cur.supernet()
out[out.index(index)] = cur
addrs.pop(0)
found = True
break
if not found:
out.append(IPv4Network(addrs.pop(0), 32).supernet())
这会给你以下结果:
In [81]: out
Out[81]: [IPv4Network('10.10.0.0/24'), IPv4Network('172.171.0.0/25')]
我并不是 100% 相信我自己的实现,但我认为这可以做得更好,这也只会合并到/8
.这至少应该让您了解如何使用 ipaddress 模块以及可以用它做什么。