在Python中将CIDR转换为子网掩码

11

我有一个Python字典,其中包含一个子网列表,格式如下:

x.x.x.x/24
y.y.y,y/25
z.z.z.z/26
a.a.a.a/27 

我想获取这个字典中的项目,进行解析,然后以以下格式呈现结果:

x.x.x.x 255.255.255.0
y.y.y.y 255.255.255.128
x.x.x.x 255.255.255.192
a.a.a.a 255.255.255.224 

我目前没有太多关于这个话题的信息,因为在网上找不到很多相关资料,也没有能够以简明扼要的方式呈现的。你有什么想法吗?


你的数据不是你所提到的字典类型! - SIslam
如果需要看一个例子,我写了一个类来实现这个功能在这里 - Adam Acosta
4个回答

15

代码:

import socket
import struct

def cidr_to_netmask(cidr):
    network, net_bits = cidr.split('/')
    host_bits = 32 - int(net_bits)
    netmask = socket.inet_ntoa(struct.pack('!I', (1 << 32) - (1 << host_bits)))
    return network, netmask

使用方法:

>>> cidr_to_netmask('10.10.1.32/27')
('10.10.1.32', '255.255.255.224')
>>> cidr_to_netmask('208.128.0.0/11')
('208.128.0.0', '255.224.0.0')
>>> cidr_to_netmask('208.130.28.0/22')
('208.130.28.0', '255.255.252.0')

1
毋庸置疑,对于IPv6启动的用户来说,CIDR是IPv6的官方表示法,因此网络掩码已经不再使用。但是如果您仍然想要使用,可以参考以下链接:https://gist.github.com/Torxed/148303f1677e56dcca794386e90299fc - Torxed

11

试试这个解决方案:

Python3

from ipaddress import IPv4Network

networks = {'n1':'10.1.0.0/21','n2':'10.2.0.0/22','n3':'10.3.0.0/23','n4':'10.4.0.0/24'}

for x,y in enumerate(networks):
    print(IPv4Network(networks[y]).network_address, IPv4Network(networks[y]).netmask)

结果:

10.1.0.0 255.255.248.0
10.2.0.0 255.255.252.0
10.3.0.0 255.255.254.0
10.4.0.0 255.255.255.0

Python2

from netaddr import IPNetwork

networks = {'n1':'10.1.0.0/21','n2':'10.2.0.0/22','n3':'10.3.0.0/23','n4':'10.4.0.0/24'}

for x,y in enumerate(networks):
    print(str(IPNetwork(networks[y]).network), str(IPNetwork(networks[y]).netmask))

结果:

('10.1.0.0', '255.255.248.0')
('10.2.0.0', '255.255.252.0')
('10.3.0.0', '255.255.254.0')
('10.4.0.0', '255.255.255.0')

apt install python-netaddr - xinthose
https://pypi.org/project/ipaddress/ 是一个“将3.3+ ipaddress模块移植到2.6、2.7、3.2”的项目,如果您仍需要维护Python2代码并想使用ipaddress,可以考虑使用该项目。 - yaobin

11

我认为我可以提供我的解决方案,因为我在阅读性方面比其他答案更加注重。

def cidr_to_netmask(cidr):
  cidr = int(cidr)
  mask = (0xffffffff >> (32 - cidr)) << (32 - cidr)
  return (str( (0xff000000 & mask) >> 24)   + '.' +
          str( (0x00ff0000 & mask) >> 16)   + '.' +
          str( (0x0000ff00 & mask) >> 8)    + '.' +
          str( (0x000000ff & mask)))

现在更容易看到正在发生的事情,具体步骤如下:

  1. 通过在前面填充1并让cidr占据其余部分来获取数字mask
  2. 对于每个位应用mask
  3. 连接所有位,用句点隔开

这是一个非常流程化的过程,不使用任何库。


0

试试这个

lsIP = []
ans = 0
CIDR = 32
IP = [1] * CIDR
for i in range(len(IP)):
    iIdx = i % 8
    if iIdx == 0:
        if i >= 8:
            lsIP.append(ans)
            ans = 0
    ans += pow(2, 7 - iIdx)
lsIP.append(ans)

[lsIP.append(0) for i in range(4 - len(lsIP))]
print lsIP

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接