我有一个包含这些IP地址的txt文件,希望对它们进行排序,删除重复的IP地址,但保留/subnet。
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有什么技巧吗?我还想按升序排序。
您应该能够使用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)
由于数据看起来非常规则,因此使用键参数可以很容易地确保Python中的正确排序。这用于为列表中要排序的每个实例创建一个"排序键"。人们经常使用lambda作为排序键函数,但为了完整性,我们将define一些有用的函数。
重复删除最好在Python中排序之前完成。由于列表无论如何都必须进行排序,因此将其转换为集合将导致唯一字符串的任意排序并不重要,如果在Python中排序无关紧要,则"uniquiify"列表l的简单方法是
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中并不重要,因为作为"装饰/排序/取消装饰"算法的一部分,它只应用于每个列表值一次。更普遍地说,对于这个问题域,你可能会发现ipad地址模块很有用:http://docs.python.org/dev/howto/ipaddress.html
在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']
您可以使用awk:按照文件中出现的顺序获得唯一的行
awk '!seen[$0]++'
如果你想要整个管道:
awk '/#/{sub(/#.*/,"",$0)} length($0) && !seen[$0]++' ipnum.txt
未经测试