从python shell运行bash命令

时间:2014-05-25 17:04:05

标签: python bash

我想从python shell运行bash命令。 我的bash是:

grep -Po "(?<=<cite>).*?(?=</cite>)" /tmp/file1.txt | awk -F/ '{print $1}' | awk '!x[$0]++' > /tmp/file2.txt

我尝试的是:

#!/usr/bin/python
import commands
commands.getoutput('grep ' + '-Po ' +  '\"\(?<=<dev>\).*?\(?=</dev>\)\" ' + '/tmp/file.txt ' + '| ' + 'awk \'!x[$0]++\' ' + '> ' + '/tmp/file2.txt')

但我没有任何结果。

谢谢

6 个答案:

答案 0 :(得分:3)

在python中运行系统命令的推荐方法是使用模块subprocess

import subprocess

a=['grep' ,'-Po', '"(?<=<dev>).*?(?=</dev>)"','/tmp/file.txt']
b=['awk', '-F/', '"{print $1}"'] 
c=["awk", '"!x[$0]++"']

p1 = subprocess.Popen(a,stdout=subprocess.PIPE)
p2 = subprocess.Popen(b,stdin=p1.stdout,stdout=subprocess.PIPE)
p3 = subprocess.Popen(c,stdin=p2.stdout,stdout=subprocess.PIPE)
p1.stdout.close()
p2.stdout.close()
out,err=p3.communicate()
print out

在每个子进程之间创建管道的目的是出于安全和调试的原因。此外,它使代码更清晰,哪个进程获取输入并将输出发送到。

答案 1 :(得分:2)

如果您想避免拆分参数并担心管道问题,可以使用shell=True选项:

cmd = "grep -Po \"(?<=<dev>).*?(?=</dev>)\" /tmp/file.txt | awk -F/ '{print $1}' | awk '!x[$0]++' > file2.txt"
out = subprocess.check_output(cmd, shell=True)

这将运行一个子shell,它将理解你的所有指令,包括“|”用于管道,“&gt;”用于重定向。如果你不这样做,通常由shell解析的这些符号将被传递给grep程序。

否则,您必须自己创建管道。例如(下面未经测试的代码):

grep_p = subprocess.Popen(["grep", "-Po", "(?<=<dev>).*?(?=</dev>)", "/tmp/file.txt"], stdout=subprocess.PIPE)
awk_p = subprocess.Popen(["awk", "-F/", "'{print $1}'"], stdin = grep_p.stdout)
file2_fh = open("file2.txt", "w")
awk_p_2 = subprocess.Popen(["awk", "!x[$0]++", stdout = file2_fh, stdin = awk_p.stdout)
awk_p_2.communicate()

但是,如果你这样做,你就错过了python的观点。您应该查看re模块:re.matchre.subre.search,尽管我不太熟悉awk来翻译您的命令。

答案 2 :(得分:1)

你必须使用

import os 
os.system(command)

答案 3 :(得分:1)

让我们编写一个简单的函数来轻松处理这些混乱的管道:

def subprocess_pipes (pipes, last_pipe_out = None):
    import subprocess
    from subprocess  import PIPE
    last_p = None
    for cmd in pipes:
        out_pipe = PIPE if not (cmd==pipes[-1] and last_pipe_out) else open(last_pipe_out, "w")
        cmd = cmd if isinstance(cmd, list) else cmd.split(" ")
        in_pipe = last_p.stdout if last_p else None
        p = subprocess.Popen(cmd, stdout = out_pipe, stdin = in_pipe)
        last_p = p
    comm = last_p.communicate()
    return comm

然后我们跑,

subprocess_pipes(("ps ax", "grep python"), last_pipe_out = "test.out.2")

结果是&#34; test.out.2&#34;带有管道内容的文件&#34; ps ax&#34;进入&#34; grep python&#34;。

在你的情况下,

a = ["grep", "-Po", "(?<=<cite>).*?(?=</cite>)", "/tmp/file1.txt"]
b = ["awk", "-F/", "{print $1}"]
c = ["awk", "!x[$0]++"]

subprocess_pipes((a, b, c),  last_pipe_out = "/tmp/file2.txt")

答案 4 :(得分:0)

commands模块现已过时。 如果您实际上不需要输出命令,可以使用

import os

exit_status = os.system("your-command")

否则你可以使用

import suproccess

out, err = subprocess.Popen("your | commands", stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell = True).communicate()

注意:对于您的命令,您将stdout发送到file2.txt,因此我不希望在out中看到任何内容,但您仍然会在stderr上看到有关err的错误消息

答案 5 :(得分:-1)

我认为你要找的是: ubprocess.check_output(same as popen arguments, **kwargs),以与使用popen命令相同的方式使用它,它应该显示正在调用的程序的输出。

有关详情,请点击此链接:http://freefilesdl.com/how-to-call-a-shell-command-from-python/