Mam plik tekstowy, który wygląda tak (blisko 1 500 000 linii z ~ 5-120 słów na linię o zmiennej długości):

This is a foo bar sentence.
What are you sure a foo bar? or a foo blah blah.
blah blah foo sheep have you any bar?
...

Chcę wyszukać linie zawierające frazę (maksymalnie 10 000 linii), powiedzmy foo bar. Więc w Pythonie napisałem to:

import os
cmd = 'grep -m 10,000 "'+frag+'" '+deuroparl + " > grep.tmp"
os.system(cmd)
results = [i for i in open('grep.tmp','r').readlines()]

Jaki jest "właściwy" sposób, aby to zrobić bez oszukiwania grep? Czy będzie szybciej niż grep (patrz Jak biegnie tak szybko? )? Czy jest szybszy sposób, aby to zrobić?

2
alvas 22 listopad 2013, 13:17

4 odpowiedzi

Najlepsza odpowiedź
with file('bla.txt') as input:
  for count, line in enumerate(input):
    if count > 10000:
      break
    if re.search('foo bar', line):
      print line

Nie sądzę, że będzie to szybciej niż grep, ponieważ ten jest zoptymalizowany, aby wykonać dokładnie to zadanie, gdy Python jest szwajcarskim nożem wojskowym.

W przypadku, gdy chcesz użyć STDIN, możesz usunąć pierwszą linię i po prostu użyjesz sys.stdin jako input.

3
Alfe 22 listopad 2013, 12:37

Możesz zminimalizować wykorzystanie pamięci za pomocą funkcji generatora:

import re

def matcher(filename, pattern, maxmatches):
    matches = 0
    pattern = re.compile(pattern)
    with open(filename) as fp:
        for line in fp:
            if pattern.match(line):
                matches += 1
                if matches > maxmatches:
                    break
                yield line.strip()

for line in matcher('whatever.txt', 'foo bar', 10000):
    print line
3
martineau 22 listopad 2013, 10:18

Aby nieco uogólniać, moduł ITertools ma bardzo przydatne metody budowania strumieni przetwarzania w stylu rur, które są wydajne:

from itertools import ifilter

def grepper(lineno, line):
  return "foo bar" in line

result = ifilter(grepper, enumerate(open("yourfile.txt")))
1
payne 22 listopad 2013, 11:21

Jeśli szukasz tylko dla określonego tekstu (np.

with open("fileName","r") as fileHandle:
    result = [line.strip() for line in fileHandle if "yourWord" in line]
             # Or use a generator above instead 
print result
0
UltraInstinct 22 listopad 2013, 09:23