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

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

2 голосов
/ 08 августа 2009
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 ]

7 голосов
/ 08 августа 2009

Самый простой способ:

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,

добавить номера строк, разрывы между блоками и т. Д. По вкусу; -).

В крайне маловероятном случае, когда вам приходится иметь дело с совершенно огромными текстовыми файлами (например, в 200-300 раз больше, чем в Библии короля Иакова, что составляет около 4,3 МБ в целом в виде текстового файла), я рекомендовать генератор, создающий скользящее окно («FIFO» из линий). Сосредоточение для простоты только на поиске строк, исключая первые и последние несколько файлов (для этого требуется дополнительно несколько циклов специального случая - вот почему я также возвращаю индекс ... потому что это не всегда 5 в эти две дополнительные петли! -):

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 голос
/ 08 августа 2009

Хотя мне нравится простота ответа Алекса, для поиска больших файлов потребуется много памяти. Как насчет этого алгоритма?

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...