Printing out subprocess when regex captures

2019-02-25 17:52发布

问题:

I am running a bash command in python with:

proc = subprocess.Popen(cmd)
proc.wait()

This cmd prints an output. However I dont want it to print unless it is captured by some regex. Not sure how to do this as this is my first time using subprocess

回答1:

You could do also pipe the output directly to grep etc..:

from subprocess import PIPE, Popen

p = Popen(["ps"], stdout=PIPE)
p2 = Popen(["grep", "chrome"],stdin=p.stdout, stdout=PIPE,universal_newlines=True)
p.stdout.close()

out,err = p2.communicate()
print(out)

 421 ?        00:00:03 chrome
 767 ?        00:00:02 chrome
 843 ?        00:00:04 chrome
 2788 ?        00:52:16 chrome
 2819 ?        00:00:00 chrome-sandbox
 2820 ?        00:00:00 chrome
 2827 ?        00:00:00 chrome-sandbox


回答2:

You can do:

proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = proc.communicate()

To check any output/error you can apply your regex on (out,err), and print whatever you want.

hope this helps.



回答3:

In the simple case you should be able to use subprocess.check_output to get the result of a call. In Python3 this returns a bytes object. In Python2 it's a str as usual.

# Python3
result_in_bytes = subprocess.check_output(cmd)
result = result_in_bytes.decode() # -> string

# Python2
result = subprocess.check_output(cmd)

Then you should be able to run your regex on that string.



回答4:

To emulate the shell pipeline:

#!/usr/bin/env python
from subprocess import Popen, PIPE

output = Popen("cmd | grep 'pattern'", shell=True,
               stdout=PIPE).communicate()[0]

without the shell:

#!/usr/bin/env python
from subprocess import Popen, PIPE

grep = Popen(['grep', 'pattern'], stdin=PIPE, stdout=PIPE)
cmd_process = Popen(['cmd'], stdout=grep.stdin)
output = grep.communicate()[0]
cmd_process.wait()

Or you could filter cmd's output in pure Python:

#!/usr/bin/env python
from subprocess import Popen, PIPE

matched_lines = []
cmd_process = Popen(['cmd'], stdout=PIPE)
with cmd_process.stdout:
    for line in iter(cmd_process.stdout.readline, b''):
        if b'pattern' in line: # or re.match(br'pattern', line)
            matched_lines.append(line)
cmd_process.wait()