2009-08-08 2 views
2
for filename in os.listdir("."): 
    for line in open(filename).xreadlines(): 
     if "foo" in line: 
      print line 

이렇게 이것은 cat filename | grep foo과 동일한 간단한 파이썬입니다. 그러나 cat filename | grep -B 5 -C 5 foo에 해당하는 코드를 수정하려면 위 코드를 어떻게 수정해야합니까?`고양이 파일 이름 | grep -B 5 -C 5 foo`

답변

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 배 이상 큰 텍스트 파일 (텍스트 파일로 전체적으로 약 4.3MB)을 처리해야하는 극히 드문 경우이지만, 저는 슬라이딩 윈도우 (sliding window) (라인의 "FIFO")를 생성하는 생성기를 권장합니다. 파일의 첫 번째와 마지막 몇 줄을 제외하고 검색하는 경우에만 단순화에 초점을 맞추고 있습니다. (추가로 두 개의 특수 사례 루프가 필요합니다. 그 이유는 인덱스를 반환하는 이유입니다. 두 여분의 루프 -)!

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

을 나는 알렉스의 대답의 단순함을 좋아하지만 큰 파일을 grepping 때, 그것은 메모리가 많이 필요합니다. 이 알고리즘은 어떻습니까?

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) 
+0

너무 거대하고 텍스트 파일을 처리하는 이례적인 (GB를?) 싸구려 틱 노트북은 일반적으로 RAM의 2 3기가바이트 (전체 킹 제임스와 함께 제공됩니다 시대에 심각한 메모리 문제를 제공하기로 성경은 약 4.4MB 크기의 텍스트 파일입니다. 이렇게 극단적 인 특수한 요구 사항에 대해서는 반복적 인 부분을 분리하는보다 단순하고 명확한 기본 접근 방식을 제안합니다. 제 대답을 편집하여 제가 의미하는 바를 보여 주도록하겠습니다. –

+0

킹 제임스 성경에서 "foo"에 대해 왜 아무도 왜 grep을 할 지 모르겠습니다. 아직도이 문제를 반복적으로 해결하는 것이 합리적이라고 생각합니다. 나는 당신의 sliding_windows 기능을 좋아합니다. – Greg