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

我想从Python代码执行上述命令。以下是我写的代码。从python代码执行Unix命令

cmd = "diff -u < (echo 'aba'| fold -w1) < (echo 'abaa' | fold -w1)" 
os.system(cmd) 

运行上面的代码,我得到了sh: 1: Syntax error: "(" unexpected错误。据我所知,unix os无法解析大括号内的echo命令。

帮我解决这个错误。

回答

2

命令在bash中正常运行,但os.system()正在执行/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。您可以通过管道diff的输出通过cat欺骗:

>>> 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)气馁。这是值得了解的,因为有很多的附加细节的subprocess文档中,包括shell=True参数的描述(强调):

在POSIX与shell=True,该壳默认为/bin/sh .... POPEN不等价的:

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

所以,现在我们知道为什么你的命令不起作用 - 这不是调用猛砸。作为mhawke建议你应该改为调用bash直接,但你应该更喜欢subprocess模块在os.system()

>>> 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 shell中,我们不需要shell=True,而且由于我们告诉Bash调用的命令是一个我们不需要反复逃避的参数,例如与mhawke一样,"""

一旦你验证了该命令的工作,你可能想从简单地调用call()到其他subprocess功能之一是更多的脚本友好的,如run(),它返回一个CompletedProcess对象,你可以检查移开。

正如让 - 弗朗索瓦·法布尔建议你可以做很多更强大的东西与subprocess,以及包括启动<()替换为单独的进程,并将它们通过管道进入呼叫diff,从而避免了需要调用bash或写的Bash语法在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'部分,那么使用'subprocess'而不是'os.system()'有什么意义? –

+0

@ Jean-FrançoisFabre“最好的方法是使用与管道连接在一起的3个Popen对象。”你是这个意思吗? – Juggernaut