2015-06-29 127 views
1

我想要使用Python 3.4提取某个系统的IP地址,我在一个文件中有大约40,000行信息​​。该文件分成每个以“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"; 
} 
+0

是'租赁..}'存储在不同行的块将打印IP?同时告诉我们你的尝试。 – ssundarraj

+0

还没有尝试,因为我不知道从哪里开始。我会打破每个块并将其存储在一个列表中。接下来我会用';'来分解它。 '分隔符。搜索SYSTEM123456789并搜索列表[0]以使用startswith(“租约”)查找IP。 – dreamzboy

+0

看起来很好。你为什么不尝试为它编写代码? – ssundarraj

回答

1

你可以组使用租赁作为分隔符与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然后检查租赁部分的第二行,如果我们发现子串然后返回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所以我们每次提取时间和搜索字符串。

如果字符串可以出现在任何地方,你可以使用任何与检查各行:

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' 

既不方法涉及在任一个时刻在存储器中存储的行多于一个的部分。

+0

这个itertool黑魔法的作品。您的帖子非常详细,可以很容易地进行。我认为itertool比嵌套2 for循环更高效。 – dreamzboy

+0

无论如何,itertools方法更简洁,更好看! –

0

走了@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的,只有当它发现系统名称

+0

这可能是我可能结束的方法,但IP是随机的。这里的关键不在于搜索IP而是系统的名称。感谢您的贡献。 – dreamzboy