【问题标题】:Python subprocess grep command returns different answer every timePython subprocess grep 命令每次返回不同的答案
【发布时间】:2013-03-14 20:51:05
【问题描述】:

我正在尝试使用 python 对文件启动 grep 代码:

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

问题是我每次启动它时都会得到不同的匹配。一些行在返回对象中被简单地跳过。就像缓冲区已被覆盖一样。我已经尝试了我在子流程中找到的所有方法来完成这项工作,但都导致了同样的问题。

有关信息,我已直接在 shell 中测试了我的 grep 命令,它运行良好,这是我作为 cmd 参数传递给我的函数的内容

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

我也尝试过使用不同的 bufsize 值(并且没有 c 值)

【问题讨论】:

  • 请提供SSCCE,包括一些在运行时提供不同值的示例输入文件。 (除非您知道平台、平台版本、Python 版本、grep 版本无关紧要,否则也请提供该信息。)
  • 我的问题已经解决了,但为了理解起见,先生,我会这样做!
  • 我实际上无法用 SSCCE 重现我的问题。通过在我的 args 中使用简单的引号,我只匹配文件中的 1 行(我应该匹配 5),但是我匹配的行永远不会改变,这与我通常会错过 1 或 2 行的实际代码相反,它们每次都在变化。我现在有点困惑,我的代码中显然还有另一件事导致了这种情况发生

标签: python random grep subprocess


【解决方案1】:

当您改为调用时,问题就消失了(在我的测试中):

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

docs for Popen 表示 shlex.split() 演示了如何将命令行参数转换为字符串列表。在他们的示例中,外部引号从单个参数中删除。

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

grep 'a|b|c' target.txt

bash 正在调用操作系统调用(Linux 上的 exec 或某些变体)来创建新的 grep 进程。 Bash 解析该命令并删除引号;它们不是 grep 选项的一部分,它们可以通过对标记进行分组来帮助 bash 扫描您的输入。 grep 将被传递一个参数的字符串数组(这就是 argv 在 C 中的含义),因此参数不需要包含引号;参数的结构和分组由字符串数组创建。

当你使用

"'keyword1|keyword2|blabla'"

在 python 中,你实际上是在传递

'keyword1|keyword2|blabla'

当你真的只希望 grep 拥有时,将 grep 作为完整的字符串

keyword1|keyword2|blabla

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

【讨论】:

  • 这无法解释为什么他每次运行它都会得到不同的结果。这可以解释为什么当他期待一些匹配(或得到的匹配少于他的预期)时,他总是没有匹配,但这不是他声称的问题。
  • 哇,这么简单...我觉得有点愚蠢,但我应该证明我已经构建了我的 cmd,首先想将其用作字符串,然后最终将其转换为列表,因为子流程的工作方式。非常感谢!
  • 经过几次测试,看来我的问题实际上已经解决了。所以我要投赞成票。你是对的,我不知道为什么这真的有效。
  • @user2171588 我已经更新了我的回复以获得更多解释。混淆可能源于我们对 bash 的熟悉。
【解决方案2】:

我无法发表评论,但我无法阻止自己提问:

为什么要在 Python 中运行 grep?和子进程??如果您正在使用 Python,那么我强烈建议您阅读 Python RE。它比 grep 强大得多,总而言之(在我看来)更易于理解和控制。

编辑:这个问题是务实的。我想知道为什么。

【讨论】:

  • 好吧,我想出了 grep 解决方案,因为我之前使用 pyparsing 来解析非常大的数据块,而性能至关重要。 Pyparsing 太慢了,以至于我决定拆分工作并使用 grep 进行预分析,从而跟踪匹配的文件/行。现在我要检查 Python RE,感谢您的评论
  • 需要一些时间来适应,只需认真阅读有关组的内容。并再次阅读。所有东西括号 (?:...) (?!...) (?
猜你喜欢
  • 2016-06-13
  • 1970-01-01
  • 2015-05-18
  • 1970-01-01
  • 1970-01-01
  • 2015-06-30
  • 2022-12-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多