从python调用的grep命令

时间:2012-03-03 01:00:51

标签: python grep

平台: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代码片段如下:

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 命令原样。

由于 Gudge。

2 个答案:

答案 0 :(得分:4)

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

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

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

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

shell使用双引号来防止对某些shell元字符进行特殊处理。 Shell元字符是shell专门处理的字符,并不会字面上传递给它执行的程序。最常用的shell元字符是“space”。 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)

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

答案 1 :(得分:1)

您可以使用python-textops3:

from textops import *

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

借助python-textops3,您可以在python内的管道中使用类unix的命令

因此无需派遣非常繁琐的进程