CIDR 是无类别域间路由的意思,以前会用A类、B类、C类地址来表示一个网段。在 CIDR 的概念里没有ABC类地址的概念,所有地址段都可以用 a.b.c.d/m 的形式来表示。其中 a.b.c.d 是 IP 地址,m 是子网掩码。这类IP段的表示法就叫 CIDR 表示法。
如何将 IP 地址范围(以开始和结束 IP 地址的形式)转换成 CIDR 表示法,这是一个常见需求。有些防火墙和 ipset 操作不支持使用不连续的网段来表示一个集合,比如 192.168.1.1-192.168.1.10 是没法转换成单一的 CIDR 的,它如果转换成 CIDR 格式,会转换成多个 CIDR 地址段,比如:
$ python3 ip_merge2.py -t ip 192.168.1.1-192.168.1.10
192.168.1.1/32
192.168.1.2/31
192.168.1.4/30
192.168.1.8/31
192.168.1.10/32
复制
即一个 IP 段是由多个 CIDR 段组成。Github 上有一个 Go 语言写的工具可以处理这种 IP 段到 CIDR 的转换,项目地址为:
https://github.com/zhanhb/cidr-merger
复制
之前也写过文章介绍过这款工具,文章地址:
这里介绍一种在 Python 下的解决方案,这样就不需要调用第三方工具了,直接在代码中即可处理 IP 段到 CIDR 的转换。后面会贴出代码,将函数包装成命令行工具后,使用方法下:
$ python3 ip_merge2.py
usage: ip_merge2.py [-h] -t {cidr,ip} input
ip_merge2.py: error: the following arguments are required: input, -t/--type
$ python3 ip_merge2.py -t ip 0.0.0.0-9.255.255.255
0.0.0.0/5
8.0.0.0/7
复制
使用前要先安装 netaddr 模块:
$ pip install netaddr
复制
用到的关键函数如下:
>>> from netaddr import IPRange
>>> def ip_range_to_cidr(ip_start, ip_end):
... cidr_list = IPRange(ip_start, ip_end)
... return cidr_list
...
>>> ip_range_to_cidr('192.168.1.1', '192.168.1.10')
IPRange('192.168.1.1', '192.168.1.10')
>>> from netaddr import IPSet
>>> IPSet(ip_range_to_cidr('192.168.1.1', '192.168.1.10'))
IPSet(['192.168.1.1/32', '192.168.1.2/31', '192.168.1.4/30', '192.168.1.8/31', '192.168.1.10/32'])
>>>
复制
Python 代码如下:
import argparse
import ipaddress
from netaddr import IPSet, IPRange
def debug(func):
def wrapper(*args, **kwargs):
print(f"Function: {func.__name__}")
print(f"Arguments: {args}")
print(f"Keyword Arguments: {kwargs}")
print()
result = func(*args, **kwargs)
return result
return wrapper
def ip_to_cidr(ip):
ip_network = ipaddress.ip_network(ip, strict=False)
return str(ip_network)
# @debug
def ip_range_to_cidr(ip_start, ip_end):
cidr_list = IPRange(ip_start, ip_end)
return cidr_list
def cidr_to_ip_range(cidr):
ip_network = ipaddress.ip_network(cidr, strict=False)
ip_range = (str(ip_network.network_address), str(ip_network.broadcast_address))
return ip_range
def main():
parser = argparse.ArgumentParser(description="Convert between CIDR and IP range")
parser.add_argument("input", help="Input CIDR, IP address, or IP range")
parser.add_argument("-t", "--type", choices=["cidr", "ip"], help="Specify input type (cidr or ip)", required=True)
args = parser.parse_args()
if args.type == "cidr":
if "/" not in args.input:
print("Error: Invalid CIDR input. Make sure to include the subnet mask.")
return
result = cidr_to_ip_range(args.input)
print(f"CIDR to IP Range: {args.input} -> {result}")
elif args.type == "ip":
if "-" in args.input:
ip_start, ip_end = map(str.strip, args.input.split("-"))
result = ip_range_to_cidr(ip_start, ip_end)
# print(f"IP Range to CIDR: {args.input} -> {IPSet(result)}")
for i in result.cidrs():
print(i)
elif "/" in args.input:
print("Error: Invalid IP input. Remove the subnet mask for IP address input.")
return
else:
result = ip_to_cidr(args.input)
print(f"IP to CIDR: {args.input} -> {result}")
if __name__ == "__main__":
main()
复制
全文完。
如果转发本文,文末务必注明:“转自微信公众号:生有可恋”。
文章转载自生有可恋,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。
评论
相关阅读
2025年4月中国数据库流行度排行榜:OB高分复登顶,崖山稳驭撼十强
墨天轮编辑部
2029次阅读
2025-04-09 15:33:27
【MySQL 30周年庆】MySQL 8.0 OCP考试限时免费!教你免费领考券
墨天轮小教习
1560次阅读
2025-04-25 18:53:11
【DBA坦白局】第一期:在小城市和一线城市做DBA,是“躺”还是“卷”?
墨天轮编辑部
1365次阅读
2025-04-10 14:17:22
Oracle Concepts(Oracle 19c):07 SQL
Ryan Bai
1021次阅读
2025-04-09 10:57:11
2025年3月国产数据库大事记
墨天轮编辑部
907次阅读
2025-04-03 15:21:16
数据库国产化替代深化:DBA的机遇与挑战
代晓磊
846次阅读
2025-04-27 16:53:22
2025 DBA 薪资观察:做 DBA 还香吗?
墨天轮编辑部
821次阅读
2025-04-24 15:53:21
2025年3月国产数据库中标情况一览:TDSQL大单622万、GaussDB大单581万……
通讯员
623次阅读
2025-04-10 15:35:48
MySQL 30 周年庆!MySQL 8.4 认证免费考!这次是认真的。。。
严少安
620次阅读
2025-04-25 15:30:58
月薪快6万的DBA,有命干不一定有命花
多明戈教你玩狼人杀
596次阅读
2025-04-18 10:36:38