比方說,我有這樣的:是否可以在傳遞給子進程的shell字符串中進行變量替換?
>>> grepstring="mystring"
>>> p = subprocess.Popen("ls -l | grep grepstring", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
我怎樣才能在subprocess.Popen
調用替換grepstring
到mystring
?
比方說,我有這樣的:是否可以在傳遞給子進程的shell字符串中進行變量替換?
>>> grepstring="mystring"
>>> p = subprocess.Popen("ls -l | grep grepstring", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
我怎樣才能在subprocess.Popen
調用替換grepstring
到mystring
?
在這裏做的正確的事情,如果可能的話,是不是做變量替換。事實上,首先不要使用shell。你真正想要的是通過grep
一個論點;你需要通過變量替換來做到這一點的唯一原因是你沒有運行grep
,你正在運行一個shell並試圖找出如何讓你按照你想要的方式運行grep
。正如Martijn Pieters所建議的那樣,如果您只想執行相當於shell ${grepstring}
的操作,那麼您可以使用Python的字符串處理命令(理想情況下爲str.format
)來執行此操作。但是,如果grepstring
中有一個空格,這將不起作用。或特殊的外殼字符。或者更糟的是,它將工作,但沒有辦法,你想讓它(例如,如果grepstring
是$(rm -rf /)
。
你可以嘗試編寫代碼來消毒,然後正確地報價,您的所有字符串,但這是一個愚蠢的錯誤,簡單的解決方案是,除了最簡單的情況外(例如文字外殼管道字符串),不用任何外殼。subprocess
文檔有一整段代替舊功能和外殼函數,其中包括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)。
使用串插,像str.format()
:
subprocess.Popen("ls -l | grep {}".format(grepstring), ...)
但不要聽從warnings on the subprocess
documentation關於你的shell執行不信任的命令。
作爲一個方面說明,當你避免使用shell時你真的更好 - 你可以很容易地避免它,因爲[替換shell管道](http://docs.python.org/3 /library/subprocess.html#replacing-shell-pipeline)在文檔顯示。這是避免有人將不可信命令送入shell管道的唯一好方法。 – abarnert