python中的grep-r

python中的grep-r,python,grep,Python,Grep,我想在python函数中实现unix命令'grep-r'。我知道commands.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

我想在python函数中实现unix命令'grep-r'。我知道commands.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) ]

但这不起作用,它没有给我任何匹配,即使在前一个函数做的地方。什么改变了?我可以把它分成一堆嵌套循环,但我更感兴趣的是简洁而不是可读性。

re.match只检查字符串的开头

使用re.search()

发件人:

Python提供了两种不同的原语 基于定期报告的业务 表达式:匹配检查是否匹配 只有在字符串的开头, 而搜索则检查匹配项 字符串中的任何位置(这是什么 默认情况下,Perl不会这样做)


您可能希望<代码>搜索()/代码>而不是<代码> Matd()>代码>以捕获行中的匹配,如

中所指出的。 此外,代码的结构和意图相当隐蔽。我已经把它缩了

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

为什么需要使用正则表达式

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)

将所有这些代码放入名为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])
#/usr/bin/python
导入操作系统
进口稀土
导入系统
def文件匹配(fname,pat):
尝试:
f=打开(fname,“rt”)
除IOError外:
返回
对于i,枚举(f)中的行:
如果选择搜索(第行):
打印“%s:%i:%s”%(fname,i+1,第行)
f、 关闭()
def grep(董事姓名,s_pat):
pat=重新编译(s_pat)
对于os.walk中的dirpath、dirname和文件名(dir\u name):
对于文件名中的fname:
fullname=os.path.join(dirpath,fname)
文件匹配(全名,pat)
如果len(sys.argv)!=三:
u=“用法:pygrep\n”
系统标准写入(u)
系统出口(1)
grep(sys.argv[1],sys.argv[2])

是的,我的代码几乎不可读,自从我读了Peter Norvig的文章后,我一直在代码中添加“我为我在一些生成器中”语句……噢,想使用强大的抽象是很自然的!在列表理解出现之前,我曾经对map()和reduce()进行了可怕的多行构造-我真的很喜欢“做这个,做所有这些”的想法,而不是“好的,做下一个……好的,做下一个……”但我知道我的同事无法解开它,电脑也一样。如果你喜欢拼写矫正器,你应该学哈斯克尔。集合上的函数映射自然要感谢链接,我一直在看haskell,但我还没有时间真正了解它+1我很快就可以自定义它,以使用更强大的更大的选项集。
#!/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])