for filename in os.listdir("."):
for line in open(filename).xreadlines():
if "foo" in line:
print line
所以这是一个简单的python,相当于cat filename | grep foo
。但是,我希望相当于cat filename | grep -B 5 -C 5 foo
,如何修改上述代码?
答案 0 :(得分:7)
最简单的方法是:
for filename in os.listdir("."):
lines = open(filename).readlines()
for i, line in enumerate(lines):
if "foo" in line:
for x in lines[i-5 : i+6]:
print x,
添加行号,块之间的间隔等,以品尝; - )。
在极不可能的情况下,你必须处理绝对令人发指的文本文件(比例如King James Bible大200-300倍,例如,整个文本文件约为4.3 MB),推荐一个生成滑动窗口的发生器(线路的“FIFO”)。只关注搜索行的简单性,不包括文件的第一个和最后几个(这需要一些特殊情况循环 - 这也是我返回索引的原因...因为它并不总是5 in那两个额外的循环! - ):
import collections
def sliding_windows(it):
fifo = collections.deque()
# prime the FIFO with the first 10
for i, line in enumerate(it):
fifo.append(line)
if i == 9: break
# keep yielding 11-line sliding-windows
for line in it:
fifo.append(line)
yield fifo, 5
fifo.popleft()
for w, i in sliding_windows(open(filename)):
if "foo" in w[i]:
for line in w: print line,
我想我会留下特殊情况循环(并担心很少行的文件;-)作为练习,因为无论如何整个事情是如此令人难以置信的假设。
只是一些提示......:关闭的“特殊情况循环”非常简单 - 只是反复删除第一行,而不添加,显然,因为没有更多要追加...索引应该仍然是总是5,当你刚刚产生一个窗口,其中5是最后一个索引(即文件的最后一行)时,你就完成了;起始情况有点微妙,因为在你读完前6行之前你不想屈服,那时索引将是0(文件的第一行)......
最后,为了获得额外的功劳,请考虑如何在非常短的文件上使用它! - )
答案 1 :(得分:1)
虽然我喜欢Alex的答案的简单性,但是在浏览大文件时需要大量内存。这个算法怎么样?
import os
for filename in (f for f in os.listdir(".") if os.path.isfile(f)):
prevLines = []
followCount = 0
for line in open(filename):
prevLines.append(line)
if "foo" in line:
if followCount <= 0:
for prevLine in prevLines:
print prevLine.strip()
else:
print line.strip()
followCount = 5
elif followCount > 0:
print line.strip()
followCount -= 1
if len(prevLines) > 5:
prevLines.pop(0)