使用子网掩码对IP地址列表进行排序,删除重复项

时间:2012-12-13 05:25:04

标签: python perl sorting ip-address

我有一个带有这些IP地址的txt文件,并希望对它们进行排序,删除重复的IP地址,但保留/子网。

4.4.4.4/32
4.2.2.2/32
4.4.4.4/32
4.2.2.2/32
4.2.2.2/28
4.4.4.4/24
2.2.2.2/32

例如:在排序和删除重复项之后,上面的内容变为

4.4.4.4/32
4.2.2.2/32
4.2.2.2/28
4.4.4.4/24
2.2.2.2/32

使用awk或perl或python的任何提示?我还想按升序排序。

4 个答案:

答案 0 :(得分:2)

您应该只能使用sort -ur

执行此操作

编辑:要在python中执行此操作,您可以执行以下操作:

with open('ipaddress.txt', 'r') as f:
    address = sorted(list(set(line for line in f)), reverse=True)
    for ad in address:
        print(ad)

答案 1 :(得分:2)

由于数据看起来非常规则,因此使用 key 参数确保在Python中正确排序是相当容易的。这用于为要排序的列表中的每个实例创建“排序键”。人们经常使用lambda作为排序键函数,但为了完整性,我们将 def 一些有用的东西。

在Python中排序之前,最好先完成重复删除。由于列表必须进行排序,因此将其转换为集合将导致唯一字符串的任意排序无关紧要,如果排序不是“单一化”列表 l 的简单方法在Python中的问题是

l = list(set(l))

顺便说一句,你的测试数据选择得当,因为它会在词法排序上正确排序(只是偶然)。因此,在地址中包含一些带有两位和三位数组件的示例会更好。所以这不再适用。我通过解释来证明非工作类型。

In [42]: data = """\
4.4.4.4/32
4.2.2.2/32
4.4.4.4/32
4.2.2.2/32
4.2.2.2/28
4.4.4.4/24
2.2.2.2/32
12.13.14.15/24
11.12.13.14/24""".splitlines()

In [43]: data.sort()

In [44]: data
Out[44]: 
['11.12.13.14/24',
 '12.13.14.15/24',
 '2.2.2.2/32',
 '4.2.2.2/28',
 '4.2.2.2/32',
 '4.2.2.2/32',
 '4.4.4.4/24',
 '4.4.4.4/32',
 '4.4.4.4/32']

In [45]: data = list(set(data))

In [46]: data.sort()

In [47]: data
Out[47]: 
['11.12.13.14/24',
 '12.13.14.15/24',
 '2.2.2.2/32',
 '4.2.2.2/28',
 '4.2.2.2/32',
 '4.4.4.4/24',
 '4.4.4.4/32']

In [48]: def sortkey(addr):
   ....:     add, pref = addr.split("/")
   ....:     a, b, c, d = (int(x) for x in add.split("."))
   ....:     return a, b, c, d, int(pref)
   ....: 

In [49]: data.sort(key=sortkey)

In [50]: data
Out[50]: 
['2.2.2.2/32',
 '4.2.2.2/28',
 '4.2.2.2/32',
 '4.4.4.4/24',
 '4.4.4.4/32',
 '11.12.13.14/24',
 '12.13.14.15/24']

排序键函数在Python中并不重要,因为它仅作为“装饰/排序/未装饰”算法的一部分应用于每个列表值一次。更一般地说,对于此问题域,您可能会发现ipaddress模块​​很有用:http://docs.python.org/dev/howto/ipaddress.html

答案 2 :(得分:1)

在python中你可以做到:

In [3]: l = []

In [4]: with open('ipaddress.txt', 'r') as input_file:
   ...:     for elem in input_file.readlines():
   ...:         if elem.strip() not in l:
   ...:             l.append(elem.strip())
   ...:

In [5]: l
Out[5]: ['4.4.4.4/32', '4.2.2.2/32', '4.2.2.2/28', '4.4.4.4/24', '2.2.2.2/32']

答案 3 :(得分:0)

您可以使用awk:

按照它们在文件中出现的顺序获取唯一的行
awk '!seen[$0]++'

如果你想要整个管道:

awk '/#/{sub(/#.*/,"",$0)} length($0) && !seen[$0]++' ipnum.txt

<子>未测试