简体   繁体   English

从python shell运行bash命令

[英]running bash command from python shell

I want to run a bash command from python shell. 我想从python shell运行bash命令。 my bash is: 我的重击是:

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

what I tried is: 我试过的是:

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

But I don't have any result. 但是我没有任何结果。

Thank you 谢谢

The recommend way to run system commands in python is to use the module subprocess . 在python中运行系统命令的推荐方法是使用模块子进程

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

The point of creating pipes between each subprocess is for security and debugging reasons. 在每个子进程之间创建管道的目的是出于安全和调试的原因。 Also it makes the code much clearer in terms, which process gets input and sends output to. 同样,它使代码在术语上更加清晰,哪个过程获取输入并将输出发送到。

If you want to avoid splitting your arguments and worrying about pipes, you can use the shell=True option: 如果要避免拆分参数并担心管道,可以使用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)

This will run a subshell which will understands all your directives, including "|" 这将运行一个子shell,该子shell可以理解您的所有指令,包括“ |” for piping, ">" for redirection. 用于管道,“>”用于重定向。 If you do not do this, these symbols normally parsed by the shell will just be passed to grep program. 如果不这样做,通常由外壳程序解析的这些符号将被传递给grep程序。

Otherwise, you have to create the pipes yourself. 否则,您必须自己创建管道。 For example (untested code below): 例如(以下未测试的代码):

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()

However, you're missing the point of python if you are doing this. 但是,如果这样做,您将失去python的意义。 You should instead look into the re module: re.match , re.sub , re.search , though I'm not familiar enough with awk to translate your commands. 相反,您应该查看re模块: re.matchre.subre.search ,尽管我对awk尚不熟悉,无法翻译您的命令。

you must use 你必须使用

import os 
os.system(command)

Let us write a simple function to easily deal with these messy pipes for us: 让我们编写一个简单的函数为我们轻松处理这些混乱的管道:

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

Then we run, 然后我们跑

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

The result is a "test.out.2" file with the contents of piping "ps ax" into "grep python". 结果是一个“ test.out.2”文件,其中将“ ps ax”管道输送到“ grep python”中。

In your case, 就你而言

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")

The commands module is obsolete now. commands模块现在已过时。 If you don't actually need the output of your command you can use 如果您实际上不需要命令的输出,则可以使用

import os

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

Otherwise you can use 否则你可以使用

import suproccess

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

Note: for your command you send stdout to file2.txt so I wouldn't expect to see anything in out you will however still see error messages on stderr which will go into err 注:您的命令发送到标准输出file2.txt所以我不希望看到任何东西out ,你会然而仍然看到标准错误,将进入错误信息err

I think what you are looking for is something like: ubprocess.check_output(same as popen arguments, **kwargs) , use it the same way you would use a popen command , it should show you the output of the program that's being called. 我认为您正在寻找的是这样的: ubprocess.check_output(same as popen arguments, **kwargs) ,使用它的方式与使用popen命令的方式相同,它应该向您显示被调用程序的输出。

For more details here is a link: http://freefilesdl.com/how-to-call-a-shell-command-from-python/ 有关更多详细信息,请参见以下链接: http : //freefilesdl.com/how-to-call-a-shell-command-from-python/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM