2014-11-25 53 views
0

我怎样才能找到最接近的匹配使用python netaddr相同的前缀长度?蟒蛇netaddr找到最接近的ip地址匹配

>>> l = ['172.27.145.130/25', '172.27.145.129/25', '172.27.145.131/25'] 
>>> myip = '172.27.145.129' 
>>> netaddr.IPAddress(myip) in netaddr.IPNetwork(l[0]) 
True 
>>> netaddr.IPAddress(myip) in netaddr.IPNetwork(l[1]) 
True 
>>> netaddr.IPAddress(myip) in netaddr.IPNetwork(l[2]) 
True 
>>> 
+0

“最接近的匹配”是什么意思?这些都是非法网络,或者是同一网络中的不同名称,具体取决于你想要定义事物的严格程度,所以它们都不比任何其他网络更接近。 – abarnert 2014-11-25 01:00:54

+0

以及最接近的比赛,我的意思是最长的比赛。对不起,混淆 – abarik 2014-11-25 01:12:03

+1

OK,那么“最长匹配”是什么意思?同样,所有这三个人都定义了完全相同的CIDR网络172.27.145.128/25,或者根本没有,所以我不知道你期望得到什么不同的结果。 – abarnert 2014-11-25 01:18:41

回答

1

你似乎在这里失去了一个关键点:你说,“所有三个IP子网是相同的网络172.27.145.128/25的一部分”,但事实并非如此;它们全都是都是那个网络,只是它的不同非标准名称。这就是IP网络的工作方式:对于N位网络,基地址的最后N位无关紧要。所以没有办法将他们与对方进行对比,并找出哪一个是“最长”或“最接近”或任何其他类型的匹配,因为它们都将完全相同。

这可能是你的意思是接口,而不是网络。一个接口在网络中有一个地址 - 例如,网络172.27.145.128/25中的地址172.27.145.130。你可以用简写127.27.145.130/25来指定。是的,接口的简写形式看起来与网络的简写形式相同,但它们不是一回事。

如果你仍然没有得到地址,网络和接口之间的区别,3.3+ Python文档有一个很好的HOWTO

虽然netaddr没有对接口的任何支持,STDLIB的ipaddress和第三方ipaddress反向移植的Python 2.6-2.7,做的。例如:

>>> l = ['172.27.145.130/25', '172.27.145.129/25', '172.27.145.131/25'] 
>>> interfaces = [ipaddress.ip_interface(x) for x in l] 
>>> interfaces[0] 
IPv4Interface('172.27.145.130/25') 
>>> interfaces[0].ip, interfaces[0].network 
(IPv4Address('172.27.145.130'), IPv4Network('172.27.145.128/25')) 

因此,也许你问的是哪个接口与给定地址共享最多位? (我仍然不确定这是你的意思,“最接近的匹配”还是“最长的匹配”,但这似乎是一个合理的猜测。)

这仍然是一个模棱两可的问题。您可以要求询问哪个接口的地址共享更多的位周期,或者哪个共享更多的位在子网内。但是由于它们都在同一个子网中,所以这并不重要。

这意味着我们甚至可以使用netaddr网络对象作为ersatz接口对象(尽管真的,最好使用ipaddress或其他实际支持接口对象的库)。

所以:

>>> l = ['172.27.145.130/25', '172.27.145.129/25', '172.27.145.131/25'] 
>>> interfaces = [netaddr.IPNetwork(interface) for interface in l] 
>>> addresses = [interface.ip for interface in interfaces] 
>>> bits = [address.bits() for address in addresses] 
>>> bits 
['10101100.00011011.10010001.10000010', 
'10101100.00011011.10010001.10000001', 
'10101100.00011011.10010001.10000011'] 
>>> myip = '172.27.145.129' 
>>> myaddress = netaddr.IPAddress(myip) 
>>> mybits = myaddress.bits() 
'10101100.00011011.10010001.10000001' 

(很明显,你可以让整个事情就是二,三线合并在一起大多数的这些步骤)

而现在我们只是比较字符串。

netaddr.IPAddress也有一个&运营商,所以我们可以让它更简单:

>>> common_bits = [(address & myaddress).bits() for address in addresses] 
>>> common_bits 
['10101100.00011011.10010001.10000000', 
'10101100.00011011.10010001.10000001', 
'10101100.00011011.10010001.10000001'] 
>>> common_bit_counts = [bits.count('1') for bits in common_bits] 
>>> common_bit_counts 
[12, 13, 13] 

还有其他的方法来解决这个。例如,每个IPAddressvalue是一个32位整数,因此您可以将它们组合在一起并以位数的形式对位进行计数,而不是字符串。但希望这可以明确地表明事情。