使用Python进行递归grep

5 投票
4 回答
23742 浏览
提问于 2025-04-16 23:17

我刚开始学习Python,想要掌握这门语言。我正在尝试用Python实现一个简单的递归grep功能,用来处理一些内容,下面是我目前写的代码。

p = subprocess.Popen('find . -name [ch]', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  for line in p.stdout.readlines():
    q = subprocess.Popen('grep searchstring %s', line, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    print q.stdout.readlines()

有没有人能告诉我怎么修正这个代码,让它能正常工作呢?

4 个回答

0
  1. 第二行的缩进会导致错误,for 需要和上面的 p 对齐。
  2. 'grep searchstring %s', line 这个写法不会替换字符串,你需要把 , 替换成 %
p = subprocess.Popen('find . -name [ch]', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  for line in p.stdout.readlines():
    q = subprocess.Popen('grep searchstring %s', line, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    print q.stdout.readlines()

按照这些修改和真实的搜索值,它在我的 OS X 系统上可以正常工作。最终的脚本是:

import subprocess
p = subprocess.Popen('find . -name *.py', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in p.stdout.readlines():
    print line
    q = subprocess.Popen('grep import %s' % line, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    print q.stdout.readlines()
4

你可以使用 python-textops3 这个工具:

举个例子,如果你想在当前目录下的所有 .py 文件中查找所有的 'import' 语句,可以这样做:

from textops import *

print('\n'.join(('.' | find('*.py') | cat() | grep('import')))) 

这个方法完全是用 Python 写的,不需要启动额外的进程。

13

你可以使用 os.walk 这个函数来遍历你的文件。想要筛选结果的话,可以用字符串方法或者正则表达式。想了解如何使用 os.walk,可以查看这个链接:http://docs.python.org/library/os.html

import os
import re

def findfiles(path, regex):
    regObj = re.compile(regex)
    res = []
    for root, dirs, fnames in os.walk(path):
        for fname in fnames:
            if regObj.match(fname):
                res.append(os.path.join(root, fname))
    return res

print findfiles('.', r'my?(reg|ex)')

关于 grep 的部分,你可以用 open 函数来循环读取文件。

def grep(filepath, regex):
    regObj = re.compile(regex)
    res = []
    with open(filepath) as f:
        for line in f:
            if regObj.match(line):
                res.append(line)
    return res

如果你想获取行号,可以考虑使用 enumerate 这个函数。

编辑补充了 grep 函数的内容

撰写回答