Python 从文件中提取信息
我在一个文件中有大约40000行信息,我想使用Python 3.4提取某个系统的IP地址。该文件分为以“lease”开头的每个块,以“}”结尾的每个块。我想搜索“SYSTEM123456789”并提取IP地址“10.0.0.2”。我该怎么做?首选的方法是什么 1) 读入文件,在列表中拆分,然后搜索?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;
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进行搜索,而是基于系统名称。谢谢你的贡献。