给定 IP 列表
list_of_ips = ['10.0.0.10', '10.0.0.11', '10.0.0.12', '10.0.0.13', '10.0.0.40', '10.0.0.43', '10.0.0.44', '10.0.0.45', '10.0.0.46', '10.0.0.47', '10.0.0.48', '10.0.0.49', '10.0.0.50', '10.0.0.51', '10.0.0.52', '10.0.0.53', '10.0.0.54', '10.0.0.55', '10.0.0.56', '10.0.0.57', '10.0.0.58', '10.0.0.59', '10.0.0.60']
如果范围内的 IP 序列或单个 IP,想要将列表折叠为带有破折号的 IP 范围。
示例:
output = ['10.0.0.10-10.0.0.13', '10.0.0.40', '10.0.0.43-10.0.0.60']
这是部分工作的代码,由于某种原因我无法获得
10.0.0.43 - 10.0.0.60
之后的最后一个范围
不确定为什么不添加
def compare_ips(ip1, ip2):
last_octet1 = int(ip1.split('.')[-1]) # splits the ip and grabs the last octet
last_octet2 = int(ip2.split('.')[-1]) # splits the ip and grabs the last octet
if last_octet1 > last_octet2:
return -1
if last_octet1 < last_octet2:
if (last_octet2 - last_octet1) == 1:
return 1
else:
print("More then 1")
return 99
return 0
range, group = [], []
for a, b in zip(list_of_ips, list_of_ips[1:]):
check = compare_ips(a, b)
if check == 1:
group.append(a)
continue
elif check == 99:
if not a in group:
check2 = compare_ips(a, b)
if check2 == 1:
group.append(a)
continue
else:
group.append(a)
if not b in range:
range.append(b)
if len(group) > 1:
range.append("{}-{}".format(group[0],group[-1]))
group = []
您可以使用
netaddr
模块来实现此目的:
pip install netaddr
https://netaddr.readthedocs.io/en/latest/tutorial_01.html#list-operations
list_of_ips = ['10.0.0.10', '10.0.0.11', '10.0.0.12', '10.0.0.13', '10.0.0.40', '10.0.0.43', '10.0.0.44', '10.0.0.45', '10.0.0.46', '10.0.0.47', '10.0.0.48', '10.0.0.49', '10.0.0.50', '10.0.0.51', '10.0.0.52', '10.0.0.53', '10.0.0.54', '10.0.0.55', '10.0.0.56', '10.0.0.57', '10.0.0.58', '10.0.0.59', '10.0.0.60']
merged_list = netaddr.cidr_merge(list_of_ips)
print(merged_list)
[IPNetwork('10.0.0.10/31'),
IPNetwork('10.0.0.12/31'),
IPNetwork('10.0.0.40/32'),
IPNetwork('10.0.0.43/32'),
IPNetwork('10.0.0.44/30'),
IPNetwork('10.0.0.48/29'),
IPNetwork('10.0.0.56/30'),
IPNetwork('10.0.0.60/32')]
现在,如果您想验证您的结果是否正确,您可以这样做:
import ipaddress
[str(ip) for y in merged_list for ip in ipaddress.IPv4Network(y)]
#output
['10.0.0.10',
'10.0.0.11',
'10.0.0.12',
'10.0.0.13',
'10.0.0.40',
'10.0.0.43',
'10.0.0.44',
'10.0.0.45',
'10.0.0.46',
'10.0.0.47',
'10.0.0.48',
'10.0.0.49',
'10.0.0.50',
'10.0.0.51',
'10.0.0.52',
'10.0.0.53',
'10.0.0.54',
'10.0.0.55',
'10.0.0.56',
'10.0.0.57',
'10.0.0.58',
'10.0.0.59',
'10.0.0.60']
netaddr
并没有完全提供您所需要的内容,但不需要太多代码即可实现:
from netaddr import cidr_merge, IPRange
def merge_ranges(ranges):
"""Yield the ranges with adjacent input ranges merged together."""
if len(ranges) == 0:
return
ranges = sorted(ranges)
(current, *rest) = ranges
for r in rest:
if r.first == current.last + 1:
current = IPRange(current.first, r.last)
else:
yield current
current = r
yield current
list_of_ips = [
'10.0.0.10',
'10.0.0.11',
'10.0.0.12',
'10.0.0.13',
'10.0.0.40',
'10.0.0.43',
'10.0.0.44',
'10.0.0.45',
'10.0.0.46',
'10.0.0.47',
'10.0.0.48',
'10.0.0.49',
'10.0.0.50',
'10.0.0.51',
'10.0.0.52',
'10.0.0.53',
'10.0.0.54',
'10.0.0.55',
'10.0.0.56',
'10.0.0.57',
'10.0.0.58',
'10.0.0.59',
'10.0.0.60',
]
networks = cidr_merge(list_of_ips)
ranges = [IPRange(n.first, n.last) for n in networks]
merged = list(merge_ranges(ranges))
print(merged)
assert merged == [
IPRange('10.0.0.10', '10.0.0.13'),
IPRange('10.0.0.40', '10.0.0.40'),
IPRange('10.0.0.43', '10.0.0.60'),
]
输出:
[IPRange('10.0.0.10', '10.0.0.13'), IPRange('10.0.0.40', '10.0.0.40'), IPRange('10.0.0.43', '10.0.0.60')]
您现在可以按照自己想要的方式格式化和呈现,我遗漏了该部分。
我会考虑添加这样的东西
merge_ranges
到netaddr
,似乎相当有用。