2013-09-23 55 views
0

比方說,我有這樣的:是否可以在傳遞給子進程的shell字符串中進行變量替換?

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

我怎樣才能在subprocess.Popen調用替換grepstringmystring

+1

作爲一個方面說明,當你避免使用shell時你真的更好 - 你可以很容易地避免它,因爲[替換shell管道](http://docs.python.org/3 /library/subprocess.html#replacing-shell-pipeline)在文檔顯示。這是避免有人將不可信命令送入shell管道的唯一好方法。 – abarnert

回答

3

在這裏做的正確的事情,如果可能的話,是不是做變量替換。事實上,首先不要使用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)。

相關問題