在 grep 上使用纯 Python?

Using pure Python over grep?

我不熟悉 grep,因为我一直在使用 Windows 系统,所以当有人建议我将这些行添加到我的代码时,我有点困惑...

grep = 'grep -E \'@import.*{}\' * -l'.format(name)
proc = Popen(grep, shell=True, cwd=info['path'], stdout=PIPE, stderr=PIPE)

根据我的理解,这是试图找到 cwd 中所有包含 @import given_file_name 的文件,对吗?

如果这就是 grep 的工作方式,我只需要在 Python 中写一些对我有用的东西,但是我担心这样做可能需要时间一件事。

该脚本位于运行 sublime_plugin.EventListener 方法 on_post_save 的 Sublime Text 3 插件中,以查找包含刚刚保存的文件名的所有文件并构建要编译的文件名列表。

def files_that_import(filename, project_root):
    files = []
    for root, dirnames, files in os.walk(project_root):
        for fn in files:
            if fn.endswith(('.scss', '.sass')):
                with open(fn, 'r') as f:
                    data = f.read()
                if re.search(r'@import.*["\']{}["\'];'.format(fn), data):
                    files.append(fn)
    return files

不知道 grep 是如何工作的,这是我能想到的最好的。但是,正如我所说,我担心扫描所有 .scss.sass 文件所花费的时间。虽然不应该有很多,但获取每个内容的内容似乎比实际情况更复杂。

已更新

我使用@nneonneo 更正更新了代码。我还注意到在我使用的代码中,它正在检查每个文件是否有自己的 @import 语句。

def files_that_import(filename, project_root):
    pattern = re.compile('''@import.*["']{}["'];'''.format(filename))
    found = []
    for root, dirnames, files in os.walk(project_root):
        for fn in files:
            if fn.endswith(('.scss', '.sass')):
                with open(fn, 'r') as f:
                    if any(pattern.search(line) for line in f):
                        found.append(fn)
    return found

更新 如果有人觉得这有用并想使用代码,我将 files = [] 更改为 found = [],因为 files 在 for 循环中定义 os.walk() 导致错误。

你基本上已经明白了。您可以通过执行以下操作提高效率:

import_pattern = re.compile(r'''@import.*["']{}["'];'''.format(fn))
with open(fn, 'r') as f:
    for line in f:
        if import_pattern.match(line):
            files.append(fn)
            break

这将扫描每一行,并在找到要查找的内容后立即中断。它应该比读取整个文件更快。