`cat filename | grep -B 5 -C 5 foo`

时间:2009-08-08 17:22:35

标签: python grep

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,如何修改上述代码?

2 个答案:

答案 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)