Grep与Python

94 投票
8 回答
372717 浏览
提问于 2025-04-15 17:08

我需要一种方法,可以通过Unix命令行使用grep来搜索文件,使用正则表达式。例如,当我在命令行输入:

python pythonfile.py 'RE' 'file-to-be-searched'

我希望在文件中搜索正则表达式 'RE',并打印出匹配的行。

这是我写的代码:

import re
import sys

search_term = sys.argv[1]
f = sys.argv[2]

for line in open(f, 'r'):
    if re.search(search_term, line):
        print line,
        if line == None:
            print 'no matches found'

但是当我输入一个文件中没有的词时,no matches found 并没有打印出来。

8 个回答

9

这段内容改编自一个关于在Python中使用grep的教程。

它接受一个文件名的列表,通过 [2:] 来获取,但没有处理任何异常情况:

#!/usr/bin/env python
import re, sys, os

for f in filter(os.path.isfile, sys.argv[2:]):
    for line in open(f).readlines():
        if re.match(sys.argv[1], line):
            print line

如果你把它当作独立的可执行文件来运行,使用 sys.argv[1]sys.argv[2:] 是可以的,这意味着你需要先执行

chmod +x

来给文件添加执行权限。

13

简洁且节省内存:

#!/usr/bin/env python
# file: grep.py
import re, sys, collections

collections.deque(map(sys.stdout.write,(l for l in sys.stdin if re.search(sys.argv[1],l))),maxlen=0)

它的工作方式类似于 egrep(没有太多的错误处理),比如:

cat input-file | grep.py "RE"

这里是一个一行代码的写法:

cat input-file | python -c "import re,sys,collections;collections.deque(map(sys.stdout.write,(l for l in sys.stdin if re.search(sys.argv[1],l))),maxlen=0)" "RE"

注意,在 Python3 中需要使用 collections.deque 这个函数,因为 map 函数现在变得比较懒惰了。

97

大家可能会问,为什么不直接用grep呢?不过假设你不能用它……

import re
import sys

file = open(sys.argv[2], "r")

for line in file:
     if re.search(sys.argv[1], line):
         print line,

这里有几点需要注意:

  • search而不是match,这样可以在字符串的任何地方查找
  • print后面加个逗号(,)可以去掉换行符(这样这一行就不会换行了)
  • argv里包含了Python文件的名字,所以变量的索引要从1开始

这个方法不能处理多个参数(就像grep那样),也不能扩展通配符(就像Unix命令行那样)。如果你想要这些功能,可以用下面的代码:

#!/usr/bin/env python3

import re
import sys
import glob

regexp = re.compile(sys.argv[1])
for arg in sys.argv[2:]:
    for fn in glob.iglob(arg):
        with open(fn) as file:
            for line in file:
                if re.search(regexp, line):
                    print(line, end='')

撰写回答