假设我有这个:
>>> grepstring="mystring"
>>> p = subprocess.Popen("ls -l | grep grepstring", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
如何在grepstring
来电中将mystring
替换为subprocess.Popen
?
答案 0 :(得分:6)
使用字符串插值,例如str.format()
:
subprocess.Popen("ls -l | grep {}".format(grepstring), ...)
但请注意warnings on the subprocess
documentation关于在shell中执行不受信任的命令。
答案 1 :(得分:3)
如果可能的话,正确的做法是不进行变量替换。事实上,首先不要使用shell。你真正想要的是传递grep
一个论点;你需要通过变量替换来做到这一点的唯一原因是你没有运行grep
,你正在运行一个shell并试图弄清楚如何让它为你运行grep
你想要的。
如果你只想做一个shell ${grepstring}
的等价物,你可以使用Python的字符串处理命令 - 理想情况下str.format
,就像Martijn Pieters所说的那样。但是,如果grepstring
中有空格,那么这将无效。或特殊的shell字符。或者更糟糕的是,将工作,但不是您想要的方式(例如,如果grepstring
是$(rm -rf /)
。
您可以尝试编写代码来清理,然后正确引用所有字符串,但这是一个傻瓜的差事。简单的解决方案是除了最简单的情况(比如文字shell管道字符串)之外,不要使用shell。 subprocess
文档有关于替换旧函数和shell函数的整个部分,其中包括Replacing shell pipeline。
所以:
grepstring="mystring"
p0 = Popen(['ls', '-l'], stdout=PIPE)
p = Popen(['grep', grepstring], stdin=p0.stdout, stdout=PIPE, stderr=PIPE)
p0.stdout.close()
现在,你有p
与原始示例中的行为相同,只是grepstring
只是Popen
的正常参数,而不是你拥有的字符串引用并消毒并填入shell字符串。
如果你正在做很多这样的事情,你可以很容易地把它包起来,或者使用PyPI上的任何69105库来为你做这些(范围从保持简单的库到使用聪明技巧的库)使你的Python管道看起来像bash)。