Python 从文件中提取信息

Python 从文件中提取信息,python,Python,我在一个文件中有大约40000行信息,我想使用Python 3.4提取某个系统的IP地址。该文件分为以“lease”开头的每个块,以“}”结尾的每个块。我想搜索“SYSTEM123456789”并提取IP地址“10.0.0.2”。我该怎么做?首选的方法是什么 1) 读入文件,在列表中拆分,然后搜索? 2) 复制文件,然后在该文件中搜索 lease 10.0.0.1 { starts 1 2015/06/29 07:22:01; ends 2 2015/06/30 07:22:01;

我在一个文件中有大约40000行信息,我想使用Python 3.4提取某个系统的IP地址。该文件分为以“lease”开头的每个块,以“}”结尾的每个块。我想搜索“SYSTEM123456789”并提取IP地址“10.0.0.2”。我该怎么做?首选的方法是什么

1) 读入文件,在列表中拆分,然后搜索?
2) 复制文件,然后在该文件中搜索

lease 10.0.0.1 {
  starts 1 2015/06/29 07:22:01;
  ends 2 2015/06/30 07:22:01;
  tstp 2 2015/06/30 07:22:01;
  cltt 1 2015/06/29 07:22:01;
  binding state active; 
  next binding state free;
  hardware ethernet 08:2e:5f:f0:8b:a1;
}
lease 10.0.0.2{
  starts 1 2015/06/29 07:31:20;
  ends 2 2015/06/30 07:31:20;
  tstp 2 2015/06/30 07:31:20;
  cltt 1 2015/06/29 07:31:20;
  binding state active; 
  next binding state free;
  hardware ethernet ec:b1:d7:87:6f:7a;
  uid "\001\354\261\327\207oz";
  client-hostname "SYSTEM123456789";
}

您可以使用GROUPBYLE作为分隔符对节进行分组:

from itertools import groupby

def find_ip(s, f):
    with open(f) as f:
        grouped = groupby(f, key=lambda x: x.startswith("lease "))
        for k, v in grouped:
            if k: # v is the lease line
                # get ip from lease line
                ip = next(v).rstrip().split()[1]
                # call next to get next element from our groupby object 
                # which is each section after lease 
                val = list(next(grouped)[1])[-2]
                # check for substring
                if val.find(s) != -1:
                    return ip.rstrip("{")
    return "No match"
使用输入文件:

In [5]: find_ip('"SYSTEM123456789"',"in.txt")
Out[5]: '10.0.0.2'
x.startswith(“lease”)
作为groupby的键将文件拆分为多个部分,
如果k
为True,则我们有一行
lease
,因此我们提取ip,然后检查lease部分的最后一行,如果找到子字符串,则返回ip

该文件被拆分为几段行,如下所示:

['  starts 1 2015/06/29 07:22:01;\r\n', '  ends 2 2015/06/30 07:22:01;\r\n', '  tstp 2 2015/06/30 07:22:01;\r\n', '  cltt 1 2015/06/29 07:22:01;\r\n', '  binding state active; \r\n', '  next binding state free;\r\n', '  hardware ethernet 08:2e:5f:f0:8b:a1;\r\n', '}\r\n']
['  starts 1 2015/06/29 07:31:20;\r\n', '  ends 2 2015/06/30 07:31:20;\r\n', '  tstp 2 2015/06/30 07:31:20;\r\n', '  cltt 1 2015/06/29 07:31:20;\r\n', '  binding state active; \r\n', '  next binding state free;\r\n', '  hardware ethernet ec:b1:d7:87:6f:7a;\r\n', '  uid "\\001\\354\\261\\327\\207oz";\r\n', '  client-hostname "SYSTEM123456789";\r\n', '}']
您可以看到最后的第二个元素是
客户机主机名
,因此我们每次都提取该元素并搜索子字符串

如果子字符串可以出现在任何地方,则可以使用any并检查每一行:

def find_ip(s, f):
    with open(f) as f:
        grouped = groupby(f, key=lambda x: x.startswith("lease "))
        for k, v in grouped:
            if k: # v is the lease line
                # get ip from lease line
                ip = next(v).rstrip().split()[1]
                # call next to get next element from our groupby object
                # which is each section after lease
                val = next(grouped)[1]
                # check for substring
                if any(sub.find(s) != -1 for sub in val):
                    return ip.rstrip("{")
    return "No match"
当您找到一个以“lease”开头的行时,您可以应用相同的逻辑,仅使用一个外部循环和一个内部循环在文件对象上迭代,然后开始内部循环,直到找到子字符串并返回ip,或者当您点击一个
}
表示节结束时中断内部循环

def find_ip(s, f):
    with open(f) as f:
        for line in f:
            if line.startswith("lease "):
                ip = line.rstrip().split()[1]
                for n_line in f:
                    if n_line.find(s) != -1:
                        return ip.rstrip("{")
                    if n_line.startswith("}"):
                        break
    return "No match"
输出:

In [9]: find_ip('"SYSTEM123456789"',"in.txt")
Out[9]: '10.0.0.2'

这两种方法都不涉及在任何时候在内存中存储一段以上的行。

与@Ijk提到的方法不同,我提出了这个方法

import re

find_ip = False

with open(f) as f:
    for line in f:
        mat = re.match(r'lease ([0-9]*.[0-9]*.[0-9]*.[0-9]*).*', line, re.M)
        if mat:
            ip = mat.group(1)
        mat = re.match(r'.* ("SYSTEM123456789").*', line, re.M)
        if mat:
            print(ip)
OP要求提供一种首选方法,这是我的方法,尽管我不是正则表达式的最佳选择。不过,我想这就是OP想要的


我更改了ip地址的正则表达式,以便它可以查找随机ip,并且仅当它找到系统名称时才会打印ip

是否将
lease..}
块存储在不同的行中?也给我们看看你试过了什么。我不知道从哪里开始。我会打破每个区块,并将其存储在一个列表中。接下来我会用“;”来打破它定界符。搜索系统123456789并搜索列表[0]以使用StartWith(“租约”)查找IP。看起来不错。为什么不试着为它编写代码呢?如果ip地址不是10.0.0.2,你会找到“SYSTEM123456789”吗?我想你会明白这是一种魔法。你的帖子很详细,很容易被人关注。我认为itertool比嵌套2 for循环更有效。不管怎样,itertool的方法更简洁、更好看!这将是我最终可能采用的方法,但IP是随机的。这里的关键不是基于IP进行搜索,而是基于系统名称。谢谢你的贡献。