从Fi提取信息

2024-05-15 09:53:38 发布

您现在位置:Python中文网/ 问答频道 /正文

我在一个文件中有大约40000行信息,我想使用python3.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";
}

Tags: 文件信息freehardwarenextactivebindingstate
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

您可以使用“租约”作为分隔符,使用groupby对节进行分组:

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的键将文件拆分为多个部分,if k是真的,我们有一行带有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', '}']

您可以看到最后的第二个元素是client-hostname,因此我们每次都提取它并搜索子字符串。你知道吗

如果子字符串可以出现在任何地方,则可以使用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'

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

相关问题 更多 >