Python子进程grep命令每次返回的结果不同

1 投票
2 回答
918 浏览
提问于 2025-04-17 19:08

我正在尝试在Python中对一个文件使用grep命令,代码如下:

def runProcess(self, cmd):
    p = subprocess.Popen(cmd, bufsize=16000, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    return iter(p.stdout.readline, b'')

问题是每次运行时得到的匹配结果都不一样。有些行在返回的结果中根本没有出现,就好像缓冲区被覆盖了一样。我尝试了各种方法来使用subprocess模块让它正常工作,但结果都是一样的问题。

为了说明情况,我直接在命令行中测试了我的grep命令,效果很好。这是我传递给函数的cmd参数:

['egrep', '-wi', '-nr', "'keyword1|keyword2|blabla'", 'test/match_inside.txt']

我还尝试过使用不同的bufsize值(当然也试过不设置值)。

2 个回答

1

我不能评论,但我忍不住想问:

为什么要在Python里面运行grep呢?而且还用到subprocess?如果你已经在用Python,我强烈建议你看看Python的正则表达式。总的来说,它比grep强大得多,而且我觉得更容易理解和控制。

补充:这个问题是实际的。我想知道原因。

2

这个问题在我的测试中,当你使用以下方式调用时就解决了:

['egrep', '-wi', '-nr', 'keyword1|keyword2|blabla', 'test/match_inside.txt']

Popen的文档说明了shlex.split()是如何将命令行参数转换成字符串列表的。在他们的例子中,单个参数的外部引号被去掉了。

编辑:我们对bash的熟悉可能会让我们产生误解。但bash只是另一种脚本语言。如果你输入

grep 'a|b|c' target.txt

bash会调用操作系统的命令(在Linux上是exec或某种变体)来创建一个新的grep进程。bash会解析这个命令并去掉引号;引号并不是grep选项的一部分,而是帮助bash扫描你的输入,通过分组来处理这些标记。grep将接收到一个字符串数组作为参数(在C语言中这就是argv),所以参数不需要用引号括起来;参数的结构和分组是由这个字符串数组来创建的。

当你在python中使用

"'keyword1|keyword2|blabla'"

时,你实际上是将

'keyword1|keyword2|blabla'

作为完整的字符串传递给grep,而你其实只想让grep接收到

keyword1|keyword2|blabla

作为argv中索引3的字符串(具体取决于前面参数的数量)。

撰写回答