<p>您可以使用“租约”作为分隔符,使用groupby对节进行分组:</p>
<pre><code>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"
</code></pre>
<p>使用输入文件:</p>
<pre><code>In [5]: find_ip('"SYSTEM123456789"',"in.txt")
Out[5]: '10.0.0.2'
</code></pre>
<p><code>x.startswith("lease ")</code>由于groupby的键将文件拆分为多个部分,<code>if k</code>是真的,我们有一行带有<code>lease</code>所以我们提取ip,然后检查lease部分的最后一行,如果找到子字符串,则返回ip。你知道吗</p>
<p>该文件被拆分为若干行,如下所示:</p>
<pre><code>[' 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', '}']
</code></pre>
<p>您可以看到最后的第二个元素是<code>client-hostname</code>,因此我们每次都提取它并搜索子字符串。你知道吗</p>
<p>如果子字符串可以出现在任何地方,则可以使用any并检查每一行:</p>
<pre><code>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"
</code></pre>
<p>您可以应用相同的逻辑,只要用一个外循环和一个内循环迭代文件对象,当您找到一个以“lease”开头的行时,就开始内循环,直到您找到子字符串并返回ip,或者当您点击一个<code>}</code>表示节结束时中断内循环。你知道吗</p>
<pre><code>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"
</code></pre>
<p>输出:</p>
<pre><code>In [9]: find_ip('"SYSTEM123456789"',"in.txt")
Out[9]: '10.0.0.2'
</code></pre>
<p>这两种方法都不涉及在任何时候在内存中存储一段以上的行。你知道吗</p>