按Python列表中IP地址的最后八位字节排序

按Python列表中IP地址的最后八位字节排序,python,networking,ip,Python,Networking,Ip,这有点让人头脑发昏(至少对我来说是这样)。我使用一个简单的Python脚本返回一个使用fping的“up”主机列表。我将每个“up”主机存储在一个Python列表中,但是list.sort()显然不会根据存储为字符串的IP地址的最后八位字节进行排序。我想按降序排序.1、.2、.3等等 下面是代码的这一部分: for addr in os.popen("fping -a -q -g " + subnet): addr = addr.rstrip('\n') addr_list.ap

这有点让人头脑发昏(至少对我来说是这样)。我使用一个简单的Python脚本返回一个使用fping的“up”主机列表。我将每个“up”主机存储在一个Python列表中,但是list.sort()显然不会根据存储为字符串的IP地址的最后八位字节进行排序。我想按降序排序.1、.2、.3等等

下面是代码的这一部分:

for addr in os.popen("fping -a -q -g " + subnet):
    addr = addr.rstrip('\n')
    addr_list.append(addr)

addr_list.sort()
for ip in addr_list:
    print ip

假设您的
地址列表
列表如下所示(您在问题中未指定):

上拆分,并使用最后一项(最后一个八位字节)作为排序键。当然,对于“127.0.0.1”和“192.168.0.1”,您可能需要根据最后的第二个八位字节、最后的第三个八位字节和第一个八位字节进行排序

因此,将此行为用作

>>> list(reversed('10.11.12.13'.split('.')))
['13', '12', '11', '10']
>>> sorted(addr_list, key=lambda ip: list(reversed(ip.split('.'))))
['127.0.0.1', '192.168.0.1', '10.11.12.13', '1.2.3.4']
请注意,
13
4
之前列出。因此,还要确保它将每个项目作为数字而不是字符串进行比较:

>>> sorted(addr_list, key=lambda ip: map(int, reversed(ip.split('.'))))
['127.0.0.1', '192.168.0.1', '1.2.3.4', '10.11.12.13']
将其分配给另一个列表或进行就地排序:

>>> addr_list.sort(key=lambda ip: map(int, reversed(ip.split('.'))))
>>> addr_list
['127.0.0.1', '192.168.0.1', '1.2.3.4', '10.11.12.13']

假设您的
地址列表
列表如下所示(您在问题中未指定):

上拆分,并使用最后一项(最后一个八位字节)作为排序键。当然,对于“127.0.0.1”和“192.168.0.1”,您可能需要根据最后的第二个八位字节、最后的第三个八位字节和第一个八位字节进行排序

因此,将此行为用作

>>> list(reversed('10.11.12.13'.split('.')))
['13', '12', '11', '10']
>>> sorted(addr_list, key=lambda ip: list(reversed(ip.split('.'))))
['127.0.0.1', '192.168.0.1', '10.11.12.13', '1.2.3.4']
请注意,
13
4
之前列出。因此,还要确保它将每个项目作为数字而不是字符串进行比较:

>>> sorted(addr_list, key=lambda ip: map(int, reversed(ip.split('.'))))
['127.0.0.1', '192.168.0.1', '1.2.3.4', '10.11.12.13']
将其分配给另一个列表或进行就地排序:

>>> addr_list.sort(key=lambda ip: map(int, reversed(ip.split('.'))))
>>> addr_list
['127.0.0.1', '192.168.0.1', '1.2.3.4', '10.11.12.13']

sort
可以将用于执行比较的函数作为参数。如果第一个参数较大,则函数接受两个输入返回
1
;如果第二个参数较大,则函数接受两个输入返回
-1
;如果出于排序目的它们相等,则函数接受两个输入返回
0
。以下是适用于您的案例的函数:

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:
        return -1
    return 0

sort
可以将用于执行比较的函数作为参数。如果第一个参数较大,则函数接受两个输入返回
1
;如果第二个参数较大,则函数接受两个输入返回
-1
;如果出于排序目的它们相等,则函数接受两个输入返回
0
。以下是适用于您的案例的函数:

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:
        return -1
    return 0

对于最后一个八位字节,您可以在键中使用
rsplit()

addr_list = [  # Thanks @aneroid
    '10.11.12.13',
    '1.2.3.4',
    '127.0.0.1',
    '192.168.0.1',
]

>>> sorted(addr_list, key=lambda x: int(x.rsplit('.', 1)[1]), reverse=True)
['10.11.12.13', '1.2.3.4', '127.0.0.1', '192.168.0.1']
这是下降的-但您的示例似乎是上升的:

>>> sorted(addr_list, key=lambda x: int(x.rsplit('.', 1)[1]))
['127.0.0.1', '192.168.0.1', '1.2.3.4', '10.11.12.13']
但我想我更喜欢按照@aneroid进行元组排序:

>>> sorted(addr_list, key=lambda x: tuple(map(int, reversed(x.split('.')))))
['127.0.0.1', '192.168.0.1', '1.2.3.4', '10.11.12.13']

对于最后一个八位字节,您可以在键中使用
rsplit()

addr_list = [  # Thanks @aneroid
    '10.11.12.13',
    '1.2.3.4',
    '127.0.0.1',
    '192.168.0.1',
]

>>> sorted(addr_list, key=lambda x: int(x.rsplit('.', 1)[1]), reverse=True)
['10.11.12.13', '1.2.3.4', '127.0.0.1', '192.168.0.1']
这是下降的-但您的示例似乎是上升的:

>>> sorted(addr_list, key=lambda x: int(x.rsplit('.', 1)[1]))
['127.0.0.1', '192.168.0.1', '1.2.3.4', '10.11.12.13']
但我想我更喜欢按照@aneroid进行元组排序:

>>> sorted(addr_list, key=lambda x: tuple(map(int, reversed(x.split('.')))))
['127.0.0.1', '192.168.0.1', '1.2.3.4', '10.11.12.13']

仅按最后一个八位字节排序是一个非常奇怪的要求,因为较高的八位字节通常会告诉您有关地址的更多信息(例如,公共路由地址的来源国/地区,较小网络的子网)

更一般地说,这将按IP地址的数字表示形式对IP地址列表进行排序:

import socket
ip_list = ['192.168.1.120', '192.168.1.30',  '127.0.0.1']

# numeric sort, leveraging inet_pton to convert valid IPv4 address
# notation to a 'packed' string of 4 bytes, which will then sort correctly.
print sorted(ip_list, key=lambda (x): socket.inet_pton(socket.AF_INET, x))

# strict string-based sort for comparison
print sorted(ip_list)
或者,如果您不想为inet\u pton使用套接字模块:

def ip2int(ipstr):
    octets = [int(x) for x in ipstr.split('.')]
    return sum( (o << (8 * 3-i) for i,o in enumerate(octets)) )
sorted(ip_list, key=ip2int)
def ip2int(ipstr):
八位位组=[int(x)表示ipstr.split('.')中的x]

返回和((o仅按最后一个八位字节排序是一个非常奇怪的要求,因为较高的八位字节通常会告诉您有关地址的更多信息(例如,公共路由地址的来源国/地区,较小网络的子网)

更一般地说,这将按IP地址的数字表示形式对IP地址列表进行排序:

import socket
ip_list = ['192.168.1.120', '192.168.1.30',  '127.0.0.1']

# numeric sort, leveraging inet_pton to convert valid IPv4 address
# notation to a 'packed' string of 4 bytes, which will then sort correctly.
print sorted(ip_list, key=lambda (x): socket.inet_pton(socket.AF_INET, x))

# strict string-based sort for comparison
print sorted(ip_list)
或者,如果您不想为inet\u pton使用套接字模块:

def ip2int(ipstr):
    octets = [int(x) for x in ipstr.split('.')]
    return sum( (o << (8 * 3-i) for i,o in enumerate(octets)) )
sorted(ip_list, key=ip2int)
def ip2int(ipstr):
八位位组=[int(x)表示ipstr.split('.')中的x]

return sum((o给我们一个列表示例。
addr\u list
.sort()之前是什么样子的?)
八位字节
?你是指数字吗?@Reblochon-IP地址中的四个数字中的每一个都被称为八位字节,因为它由8位表示。例如,在IP地址192.168.1.101中,第一个八位字节是192,第二个八位字节是168,等等。你到底为什么要按最后一个八位字节排序?不说这样的情况有用的东西是不存在的……它真的很奇怪。给我们一个你的列表的例子。
addr\u list
.sort()之前是什么样子的
八位字节
?你是指数字吗?@Reblochon-IP地址中的四个数字中的每一个都被称为八位字节,因为它由8位表示。例如,在IP地址192.168.1.101中,第一个八位字节是192,第二个八位字节是168,等等。你到底为什么要按最后一个八位字节排序?不说这样的情况有用的东西是不存在的……这真的很奇怪。你可能需要在这里的某个地方对int进行强制转换,否则,它们将按字母顺序而不是数字顺序排序,正如你的最后一个示例所示(.13在.4之前,但应该是相反的)。您可能需要在此处某处将强制转换为int,否则,他们将按字母顺序而不是数字进行排序,如您的最后一个示例所示(.13在.4之前,但应该是相反的)。
cmp
总是比
key
慢,因为它需要“转换”列表中的每个条目都有两个参数。这确实适用于更复杂的对象,因为排序不像简单的整数转换那样直接。@Brian谢谢你的提示!我不知道这一点。这一个也很好--非常有效。感谢加载。我很高兴它有帮助!没问题!
cmp
总是这样s比
键慢,因为它需要“转换”列表中的每个条目都有两个参数。这确实适用于更复杂的对象,在这些对象中,排序不像简单的整数转换那样直接。@Brian谢谢你的提示!我不知道这一点。这一个也很好--非常有效。感谢加载。我很高兴它有帮助!没问题!同意--通常它是w