2017-02-25 15 views
1
diff -u <(echo "aba"| fold -w1) <(echo "abaa" | fold -w1) 

私はPythonコードから上記のコマンドを実行します。以下は私が書いたコードです。PythonコードからUnixコマンドを実行

上記のコードを実行すると、sh: 1: Syntax error: "(" unexpectedエラーが発生します。私の知る限りでは、UNIX OSは中括弧の中にあるエコーコマンドを解析できません。

このエラーを修正するのに手伝ってください。

答えて

2

コマンドはbashで正常に実行されますが、は/bin/shでコマンドを実行しています。あなたがチェックすることができます。

>>> os.system('echo $0') 
sh 
0 

/bin/shで実行する場合、コマンドが失敗します。

[[email protected] ~]$ /bin/sh 
sh-4.3$ diff -u <(echo "aba"| fold -w1) <(echo "abaa" | fold -w1) 
sh: syntax error near unexpected token `(' 
sh-4.3$ 

あなたが明示的にこのようなbashでコマンドを実行できます。

>>> os.system("""bash -c 'diff -u <(echo "aba"| fold -w1) <(echo "abaa" | fold -w1)'""") 
--- /dev/fd/63 2017-02-26 09:18:14.633395225 +1100 
+++ /dev/fd/62 2017-02-26 09:18:14.633395225 +1100 
@@ -1,3 +1,4 @@ 
a 
b 
a 
+a 
256 

ますので、おそらくあなたが通常できるコマンドの出力に興味がありますコマンドを実行してその出力を収集するにはsubprocess.check_output()を使用してください。残念ながらdiffは、入力ファイルの違いを検出したときにゼロ以外の終了コードを返すのが好きなので、単にcheck_outputを使用しないようにします。あなたはcatを通じてdiffの出力をパイプでごまかすことができます。

>>> from subprocess import check_output 
>>> output = check_output(['bash', '-c', 'diff -u <(echo "aba"| fold -w1) <(echo "abaa" | fold -w1) | cat']) 
>>> print(output) 
b'--- /dev/fd/63\t2017-02-26 10:02:56.814044987 +1100\n+++ /dev/fd/62\t2017-02-26 10:02:56.814044987 +1100\[email protected]@ -1,3 +1,4 @@\n a\n b\n a\n+a\n' 

>>> print(str(output, encoding='utf8')) 
--- /dev/fd/63 2017-02-26 10:02:56.814044987 +1100 
+++ /dev/fd/62 2017-02-26 10:02:56.814044987 +1100 
@@ -1,3 +1,4 @@ 
a 
b 
a 
+a 
+1

最良の方法は、パイプと一緒にチェーン3 'Popen'オブジェクトを使用することであろうことができます。 –

+0

@ Jean-FrançoisFabre:それは本当ですが、それはあなたの視点にかかっています。 OPは 'os.system()'について質問しています。 – mhawke

+0

私はあなたの答えを批判していませんでしたが、質問:+1は私のものです。私はその答えではなく、その質問にコメントしたはずです。私はPythonで3つのパイプを書こうとしていないためにあなたを非難することはできません! –

2

まず、os.system()subprocess.call(cmd, shell=True)の賛成で推奨されていません。追加の詳細の多くはshell=Trueパラメータのこの記述を含め、subprocessマニュアルにありますので、それを知っている価値がある(強調は追加):shell=TrueとPOSIXで

シェルのデフォルト/bin/sh .... popenのに同等ん:あなたのコマンドが動作しない理由を

Popen(['/bin/sh', '-c', args[0], args[1], ...]) 

は、だから今、私たちは知っている - それはバッシュを呼び出していません。 mhawkeが示唆するように、あなたの代わりに直接bashを呼び出す必要がありますが、subprocessモジュールos.system()オーバー好む必要があります。我々は、明示的にバッシュシェルを起動していることから、我々はshell=Trueを必要としない、ということ

>>> subprocess.call(['/bin/bash', '-c', 'diff -u <(echo "aba"| fold -w1) <(echo "abaa" | fold -w1)']) 
--- /dev/fd/63 2017-02-25 14:32:49.000000000 -0800 
+++ /dev/fd/62 2017-02-25 14:32:49.000000000 -0800 
@@ -1,3 +1,4 @@ 
a 
b 
a 
+a 
1 

注意をし、以来、私たちがBashに呼び出すコマンドは、それらを繰り返しエスケープする必要のない単一の引数です。 mhawkeと同じように"""となりました。あなたは、このコマンドの動作を確認したら

は、あなたはおそらく、あなたが調べることができますCompletedProcessオブジェクトを返す、などrun()として、より多くのスクリプトフレンドリーであることだけでsubprocess他の機能の一つにcall()を呼び出すことから離れて移動することをお勧めします。

ジャン・フランソワ・ファーブルは、あなたがこれbashを呼び出すか、バッシュの構文を記述する必要が避けて、別のプロセスのように<()置換を開始しdiffへのコールにそれらをパイプ含め、同様subprocessで、より多くの強力なことを行うことができます通りPythonで。もっと冗長ですが、より拡張性と保守性があります。

+1

とポータブルも、あなたは 'diff'と' fold'をウィンドウにインストールすればよいでしょう。 –

0

か、

import subprocess 
cmd = """bash -c 'diff -u <(echo "aba"| fold -w1) <(echo "abaa" | fold -w1)'""" 

ps = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 
output = ps.communicate()[0] 
+0

3つのサブプロセスオブジェクトを使っていない状態で 'shell = True'部分を削除しないと、' os.system() 'の代わりに' subprocess'を使用する点は何ですか? –

+0

@ Jean-FrançoisFabre "パイプでつながれた3つのPopenオブジェクトを使うのが最善の方法です。"これはあなたの意味ですか? – Juggernaut

関連する問題