0

假设我有这个:

>>> grepstring="mystring"
>>> p = subprocess.Popen("ls -l | grep grepstring", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

我如何在通话中替换grepstring为?mystringsubprocess.Popen

4

2 回答 2

6

使用字符串插值,例如str.format()

subprocess.Popen("ls -l | grep {}".format(grepstring), ...)

但是请注意文档中有关在 shell 中执行不受信任的命令的警告。subprocess

于 2013-09-23T20:54:37.553 回答
3

如果可能的话,正确的做法是不要进行变量替换。而且,事实上,首先不要使用外壳。你真正想要的是传递grep一个论点;你需要通过变量替换来做到这一点的唯一原因是你没有运行grep,你正在运行一个 shell 并试图弄清楚如何让它以grep你想要的方式为你运行。

如果你只想做一个 shell 的等价物${grepstring},你可以用 Python 的字符串处理命令来做 - 理想情况下str.format,正如 Martijn Pieters 所建议的那样。grepstring但是,如果其中有空间,这将不起作用。或特殊的外壳字符。或者,更糟糕的是,它工作,但不是你想要的方式(例如,如果grepstring$(rm -rf /).

您可以尝试编写代码来清理所有字符串,然后正确引用,但这是愚蠢的差事。简单的解决方案是除了最简单的情况(如文字 shell 管道字符串)之外,不使用 shell。文档有一整subprocess节关于替换旧函数和 shell 函数,其中包括替换 shell 管道

所以:

grepstring="mystring"
p0 = Popen(['ls', '-l'], stdout=PIPE)
p = Popen(['grep', grepstring], stdin=p0.stdout, stdout=PIPE, stderr=PIPE)
p0.stdout.close()

现在,您的 ap与原始示例中的行为相同,除了它grepstring只是 的普通参数Popen,而不是您必须引用和清理并填充到 shell 字符串中的字符串。

如果你做了很多这样的事情,你可以很容易地把它包起来,或者使用 PyPI 上为你做的任何 69105 库(范围从保持简单的库到使用巧妙技巧的库) Python 管道看起来像 bash)。

于 2013-09-23T21:22:37.720 回答