如何使用 python3 对 csv 文件中的 ip 地址进行排序

How to sort ip addresses in csv file using python3

我有一个如下所示的 csv 文件:

IP Address,Port,Protocol,State
192.168.3.1,53,tcp,open
192.168.13.100,80,tcp,open
192.168.3.1,443,tcp,close
192.168.3.71,1080,tcp,open
192.168.3.7,8888,tcp,open
192.168.23.12,80,tcp,filtered
192.168.3.12,443,tcp,open
192.168.3.12,631,tcp,open

如何在 python 3 中先按 IP 地址排序,然后按端口号排序?

我试过用这个:

#!/bin/python3
# import modules 
import csv, ipaddress
  
data = csv.reader(open('list.csv'),delimiter=',')
  
data = sorted(data, key = ipaddress.IPv4Address)    
  
print('After sorting:')
print(data)

但是我得到了一个ipaddress.AddressValueError: Only decimal digits permitted in "['192" in "['192.168.3.1', '53', 'tcp', 'open']"

在按 IP 地址排序后,代码接下来应该检查端口,因为有可能 IP 地址相同但端口不同。

一个多星期以来,我一直在努力解决这个问题。谢谢

第一个问题是来自您的 csv reader 的数据包括 header 行。要跳过第一行,只需使用 reader 中的一行,然后再执行其他操作。

data = csv.reader(open('list.csv'),delimiter=',')
next(data) # Consumes the header line

data = sorted(...)

旁注:使用 with 以便在退出 with 块时自动关闭文件。

with open('list.csv') as file:
    data = csv.reader(file)
    next(data)
    data = sorted(...)

现在,key 参数采用 函数 并传递 您正在排序的可迭代对象的每个元素 功能。现在你的 data 是一个迭代器,其中每个元素都是一个 list 代表 csv 文件的每一行。您不想为每一行传递整个列表,您只想传递所述列表的第一个元素。您可以使用 lambda expression 作为获取每个列表的键,并仅将第一个元素传递给 ipaddress.IPv4Address.

data = sorted(data, key = lambda row: ipaddress.IPv4Address(row[0]))

因为你还想按端口排序,你可以让你的 lambda return 一个包含 IP 地址和端口号的元组。

data = sorted(data, key = lambda row: (ipaddress.IPv4Address(row[0]), row[1]))

如果您将 data 中的第一列转换为 IPv4Address objects,您可能会发现它很有用,这样您就可以在别处使用它们。在这种情况下,请阅读您的 csv 文件 line-by-line 并在排序之前执行此操作。

with open('list.csv') as file:
    reader = csv.reader(file)
    next(reader)
    data = []
    for row in reader:
        row[0] = ipaddress.IPv4Address(row[0])
        data.append(row) 

    data.sort()

在这里,你不需要使用lambda函数,因为列表比较会自动比较第一个元素,然后是第二个元素,依此类推,并且行的元素已经是比较正确的类型。