简体   繁体   English

在Python列表中的IP地址的最后一个八位位组上排序

[英]Sort on the last octet of an IP address in a Python list

Here's a bit of a brain boggler (for me at least). 这有点令人困惑(至少对我而言)。 I'm utilizing a simple Python script to return a list of "up" hosts using fping. 我正在使用一个简单的Python脚本使用fping返回“启动”主机的列表。 I'm storing each "up" host in a Python list, however the list.sort() won't obviously sort based on the last octet of the IP address stored as a string. 我将每个“ up”主机存储在Python列表中,但是list.sort()显然不会基于存储为字符串的IP地址的最后一个八位位组进行排序。 I'd like to sort descending .1, .2, .3, etc. 我想对降序的.1,.2,.3等进行排序。

Here's that portion of the code: 这是代码的一部分:

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

For just the last octet you can use rsplit() in the key: 对于最后一个八位位组,您可以在密钥中使用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']

Which is descending - but your example seemed to be ascending: 哪个在下降-但您的示例似乎在上升:

>>> 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']

But think I would prefer a tuple sort as per @aneroid: 但是我想我更喜欢按照@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']

Assuming your addr_list list looks like this (you haven't specified it in your question): 假设您的addr_list列表如下所示(您尚未在问题中指定它):

addr_list = [
    '10.11.12.13',
    '1.2.3.4',
    '127.0.0.1',
    '192.168.0.1',
]

Split on the . 在上分裂. 's and use the last item (the last octet) as the key to your sort. ,并使用最后一项(最后一个八位位组)作为排序的键。 Of course, for '127.0.0.1' vs '192.168.0.1' you then probably want to then sort against the 2nd-last octet, and then the 3rd-last octet and then the first. 当然,对于“ 127.0.0.1”和“ 192.168.0.1”,您可能想要然后对倒数第二个字节进行排序,然后对倒数第三个字节进行排序,然后对第一个字节进行排序。

So using this behaviour as the key : 因此,使用此行为作为key

>>> 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']

Notice that 13 got listed before 4 . 注意134之前被列出。 So also ensure that it compares each item as a number and not a string: 因此,还要确保将每个项目都比较为数字而不是字符串:

>>> 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']

Either assign that to another list or do an in-place sort: 将其分配给另一个列表或进行就地排序:

>>> 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 can take as an argument a function is uses to perform the comparison. sort可以将函数用于执行比较作为参数。 The function takes two inputs returns 1 if the first argument is considered greater, -1 if the second argument is greater, and 0 if they are equal for the purposes of sorting. 该函数接受两个输入,如果第一个参数较大,则返回1如果第二个参数较大,则返回-1 0如果它们相等,则返回0 ,以进行排序。 Here is such a function for your case: 这是适合您的情况的功能:

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

You then just supply that as a keyword argument to sort: 然后,您只需将其作为关键字参数进行排序即可:

>>> ips = ['192.168.1.101', '251.39.0.103', '127.0.0.1']
>>> ips.sort(cmp = compare_ips)
>>> ips
['127.0.0.1', '192.168.1.101', '251.39.0.103']

Sorting by just the last octet is a very bizarre requirement, given that the higher octets usually tell you more about the address (eg country/region of origin for publicly routable addresses, subnet for smaller networks). 鉴于最后一个八位位组通常会告诉您有关地址的更多信息(例如,可公开路由的地址的国家/地区,较小网络的子网),仅按最后一个八位位组进行排序是一个非常奇怪的要求。

More generically, this will sort a list of IP addresses by their numeric representation: 更笼统地说,这将按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)

Or if you'd prefer not to use the socket module for inet_pton: 或者,如果您不想为inet_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)
addr_list = [
    '10.11.12.3',
    '1.2.3.4',
    '127.0.0.1',
    '192.168.0.2',
]

# lambda x=192.168.0.2 , ip.split= ['192','168','0','2'][-1] = 2
sorted_ips = sorted(addr_list , key=lambda ip: ip.split('.')[-1])
for ip in sorted_ips:
  print(ip)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM