grep -r в питоне - PullRequest
       39

grep -r в питоне

4 голосов
/ 08 декабря 2009

Я бы хотел реализовать команду unix 'grep -r' в функции python. я знаю о command.getstatusoutput (), но сейчас я не хочу использовать это. я придумал это:

def grep_r (str, dir):
    files = [ o[0]+"/"+f for o in os.walk(dir) for f in o[2] if os.path.isfile(o[0]+"/"+f) ]
    return [ l for f in files for l in open(f) if str in l ]

но это, конечно, не использует регулярное выражение, оно просто проверяет, является ли 'str' подстрокой 'l'. поэтому я попробовал следующее:

def grep_r (pattern, dir):
    r = re.compile(pattern)
    files = [ o[0]+"/"+f for o in os.walk(dir) for f in o[2] if os.path.isfile(o[0]+"/"+f) ]
    return [ l for f in files for l in open(f) if r.match(l) ]

но это не работает, это не дает мне совпадений даже там, где работала предыдущая функция. что изменилось? я мог бы просто разбить его на несколько вложенных циклов, но меня больше интересует краткость, чем читаемость.

Ответы [ 5 ]

9 голосов
/ 08 декабря 2009

Возможно, вы захотите search() вместо match(), чтобы перехватывать совпадения в середине строки, как отмечено в http://docs.python.org/library/re.html#matching-vs-searching

Кроме того, структура и назначение вашего кода довольно скрыты. Я питонизировал это.

def grep_r (pattern, dir):
    r = re.compile(pattern)
    for parent, dnames, fnames in os.walk(dir):
        for fname in fnames:
            filename = os.path.join(parent, fname)
            if os.path.isfile(filename):
                with open(filename) as f:
                    for line in f:
                        if r.search(line):
                            yield line
6 голосов
/ 08 декабря 2009

re.match проверяет только начало строки.

Используйте re.search ()

С Документы :

Python предлагает два разных примитива операции на основе регулярного выражения: проверка на совпадение только в начале строки, пока поиск проверяет совпадение где-нибудь в строке (это то, что Perl делает по умолчанию).

3 голосов
/ 08 декабря 2009

Поместите весь этот код в файл с именем pygrep и chmod + x pygrep:

#!/usr/bin/python

import os
import re
import sys

def file_match(fname, pat):
    try:
        f = open(fname, "rt")
    except IOError:
        return
    for i, line in enumerate(f):
        if pat.search(line):
            print "%s: %i: %s" % (fname, i+1, line)
    f.close()


def grep(dir_name, s_pat):
    pat = re.compile(s_pat)
    for dirpath, dirnames, filenames in os.walk(dir_name):
        for fname in filenames:
            fullname = os.path.join(dirpath, fname)
            file_match(fullname, pat)

if len(sys.argv) != 3:
    u = "Usage: pygrep <dir_name> <pattern>\n"
    sys.stderr.write(u)
    sys.exit(1)

grep(sys.argv[1], sys.argv[2])
2 голосов
/ 08 декабря 2009
import os, re

def grep_r(regex, dir):
    for root, dirs, files in os.walk(dir):
        for f in files:
            for m in grep(regex, os.path.join(root, f)):
                yield m

def grep(regex, filename):
    for i, line in enumerate(open(filename)):
        if re.match(regex, line): # or re.search depending on your default
           yield "%s:%d: %s" % (os.path.basename(filename), i+1, line)
1 голос
/ 08 декабря 2009

зачем вам нужно использовать регулярные выражения?

path=os.path.join("/dir1","dir2","dir3")
pattern="test"
for r,d,f in os.walk(path):
    for files in f:
        for n,line in enumerate(open( os.path.join(r,files) ) ):
            if pattern in line:
                print "%s found in line: %d of file: %s" %(pattern, n+1, files)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...