【问题标题】:grep command called from python从 python 调用的 grep 命令
【发布时间】:2012-03-03 01:00:51
【问题描述】:

平台:Windows

Grep:http://gnuwin32.sourceforge.net/packages/grep.htm

Python:2.7.2

用于执行命令的 Windows 命令提示符。

我正在文件中搜索以下模式"2345$"。 文件内容如下:

abcd    2345

2345

abcd    2345$

grep "2345$" file.txt

grep 成功返回 2 行(第一行和第二行)。

当我尝试通过 python 运行上述命令时,我看不到任何输出。 Python代码sn-p如下:

temp = open('file.txt', "r+")
grep_cmd = []
grep_cmd.extend([grep, '"2345$"' ,temp.name])
print grep_cmd
p = subprocess.Popen(grep_cmd, 
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE)
stdoutdata = p.communicate()[0]
print stdoutdata

如果我有

grep_cmd.extend([grep, '2345$' ,temp.name])

在我的 python 脚本中,我得到了正确的答案。

问题是为什么 grep 命令带有"

grep_cmd.extend([grep, '"2345$"' ,temp.name])

从 python 执行失败。 python不应该执行吗 命令原样。

谢谢 猜测。

【问题讨论】:

  • 很抱歉没有直接回答您的问题,但是您有什么理由不想在 python 中手动“grep”文件?例如,使用re?会少很多行...
  • 我知道我可以做一个 re.search。具体要求通过python执行命令。
  • 好的,很公平@gudge。不要误会我的意思,只是想确保你知道你在做什么:)

标签: python grep


【解决方案1】:

不要在你的模式周围加上双引号。仅需要在命令行上引用 shell 元字符。从python调用程序时,不需要这个。

您也不需要自己打开文件 - grep 会这样做:

grep_cmd.extend([grep, '2345$', 'file.txt'])

要了解不需要双引号并导致命令失败的原因,您需要了解双引号的用途以及它们的处理方式。

shell 使用双引号来防止对某些 shell 元字符进行特殊处理。 Shell 元字符是 Shell 专门处理的那些字符,它们不会按字面意思传递给它执行的程序。最常用的 shell 元字符是“空格”。 Shell 在空间边界上拆分命令以构建参数向量来执行程序。如果要在参数中包含空格,则必须以某种方式引用它(单引号或双引号、反斜杠等)。另一个是美元符号($),用于表示变量扩展。

当您在没有涉及 shell 的情况下执行程序时,所有这些关于引用和 shell 元字符的规则都不相关。在python中,您自己构建参数向量,因此相关的引用规则是python引用规则(例如,在双引号字符串中包含双引号,在双引号前加上反斜杠 - 反斜杠不会在最后细绳)。参数向量的每个元素中的字符在您完成构造后将被传递给您正在执行的程序。

Grep 不会将双引号视为特殊字符,因此如果 grep 在其搜索模式中获取双引号,它将尝试匹配其输入中的双引号。

我最初的答案对 shell=True 的引用不正确 - 首先我没有注意到您最初指定了 shell=True,其次我是从 Unix/Linux 实现的角度来看的,而不是 Windows。

python 子进程模块页面有关于 shell=True 和 Windows 的说明:

在 Windows 上:Popen 类使用 CreateProcess() 来执行子子程序,该子程序对字符串进行操作。如果 args 是一个序列,它将按照Converting an argument sequence to a string on Windows 中描述的方式转换为字符串。

关于在 Windows 上将参数序列转换为字符串的链接部分对我来说没有意义。首先,一个字符串是一个序列,一个列表也是如此,但“常用参数”部分对参数是这样说的:

args 是所有调用所必需的,它应该是一个字符串,或一系列程序参数。提供一系列参数通常是首选,因为它允许模块处理任何所需的参数转义和引用(例如,允许文件名中的空格)。

这与 Python 文档中描述的转换过程相矛盾,鉴于您观察到的行为,我会说文档是错误的,并且仅适用于参数字符串,而不适用于参数向量。我自己无法验证这一点,因为我没有 Windows 或 Python 的源代码。

我怀疑如果你打电话给subprocess.Popen 喜欢:

p = subprocess.Popen(grep + ' "2345$" file.txt', stdout=..., shell_True)

您可能会发现双引号已作为记录的参数转换的一部分被删除。

【讨论】:

  • 它在没有双引号的情况下工作。但它不应该也适用于双引号。如果我没记错的话,Python 应该按原样选择数组的内容。如果是这种情况,那么通过 python 执行的 grep 命令(带双引号)应该返回这两行。
  • @grudge:当你把双引号放在单引号里面时,双引号成为模式的一部分。显然,您的文件中没有引号,因此不匹配。请记住,当您从命令行调用 grep 时,shell 会在 grep 看到它们之前删除引号。
  • gudge:我已经更新了我的答案,以扩展如何处理参数并评论我认为可能直接导致您困惑的错误。
【解决方案2】:

你可以使用 python-textops3 :

from textops import *

print('\n'.join(cat('file.txt') | grep('2345$')))

使用 python-textops3,您可以在 python 中使用类似 unix 的命令和管道

所以不需要分叉一个非常繁重的进程

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-19
    • 1970-01-01
    • 2013-11-29
    • 1970-01-01
    • 1970-01-01
    • 2016-10-28
    • 1970-01-01
    相关资源
    最近更新 更多