0

私がこれを持っているとしましょう:

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

通話で を代用grepstringするmystringにはどうすればよいですか?subprocess.Popen

4

2 に答える 2

6

次のような文字列補間を使用しますstr.format()

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

ただし、シェルでの信頼できないコマンドの実行に関するドキュメントの警告に注意してください。subprocess

于 2013-09-23T20:54:37.553 に答える
3

ここで行うべき正しいことは、可能であれば、変数置換を行わないことです。そして、実際には、そもそもシェルを使用しないことです。本当に必要なのはgrep、引数を渡すことです。変数置換を介してそれを行う必要がある唯一の理由は、実行していないためですgrep。シェルを実行していて、それを希望どおりに実行する方法を見つけようとしていgrepます。

shell と同等のことをしたいだけなら${grepstring}、Python の文字列処理コマンドを使ってそれを行いますstr.format。Martijn Pieters が示唆しているように、理想的には です。grepstringただし、たとえば、スペースが含まれている場合、これは機能しません。または特殊なシェル文字。または、さらに悪いことに、それ機能しますが、希望どおりにはなりません (たとえば、 if grepstringis $(rm -rf /).

すべての文字列をサニタイズして適切に引用するコードを書くことはできますが、それはばかげたことです。簡単な解決策は、最も単純なケース (文字通りのシェル パイプライン文字列など) 以外にはシェルを使用しないことです。subprocessドキュメントには、古い関数とシェル関数の置き換えに関するセクション全体があり、これにはシェル パイプラインの置き換えが含まれます

そう:

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

pこれで、元の例と同じように動作するa が得られましたが、これはgrepstringへの通常の引数Popenであり、引用してサニタイズし、シェル文字列に詰め込む必要のある文字列ではありません。

これをたくさん行っている場合は、これを非常に簡単にまとめることができます。または、PyPI でそれを行う 69105 ライブラリのいずれかを使用できます (単純なライブラリから、巧妙なトリックを使用してPython パイプラインは bash のように見えます)。

于 2013-09-23T21:22:37.720 に答える