Eu quero capturar uma coluna específica de uma saída de comando usando o python 3

0

Em uma máquina Ubuntu eu quero capturar a segunda coluna da saída do comando "dpkg -l". Eu uso o python 3 e quero usar o módulo subprocessado. o seguinte comando:

fh=open("/tmp/test.out", 'wb')
with subprocess.Popen(["dpkg", "-l"], stdout=subprocess.PIPE) as proc:
   fh.write(proc.stdout.read())

retorna como abaixo:

ii yum 3.4.3-3 all Advanced front-end for rpm  
ii zeitgeist-core 1.0-0ubuntu4 amd64 event logging framework - engine  
ii zenity 3.24.0-1 amd64 Display graphical dialog boxes from shell scripts  
ii zenity-common 3.24.0-1 all Display graphical dialog boxes from shell scripts   
ii zip 3.0-11build1 amd64 Archiver for .zip files  
ii zita-ajbridge 0.7.0-1 amd64 alsa to jack bridge  
ii zita-at1 0.6.0-1 amd64 JACK autotuner  
ii zita-lrx 0.1.0-3 amd64 Command line jack application providing crossover filters  
ii zita-mu1 0.2.2-2 amd64 organise stereo monitoring for Jack Audio Connection Kit  
.....  
.....  

Eu quero pegar a segunda coluna, exemplo:

....  
....  
yum  
zeitgeist-core  
zenity  
zenity-common  
zip  
....  
.... etc etc  

Por favor ajude

>>> with subprocess.Popen(["dpkg", "-l"], stdout=subprocess.PIPE) as proc:
...     line1=proc.stdout.read()
...     type(line1)
...
<class 'bytes'>

o tipo é bytes. Como dividir Quando eu uso o seguinte:

>>> with subprocess.Popen(["dpkg", "-l"], stdout=subprocess.PIPE) as proc:
...     line1=proc.stdout.read()
...     line2=str(line)  # the type is byte so I try to convert to string
...     print(line2)
...
10

(A saída está desarrumada)

    
por Ravi OpenSource 09.02.2018 / 00:27

3 respostas

2

Sua maneira de obter a saída de chamadas do sistema é bastante desatualizada. Use

subprocess.check_output()

em vez disso:

#!/usr/bin/env python3
import subprocess

f = "/home/jacob/Desktop/output.txt"

lines = subprocess.check_output(["dpkg", "-l"]).decode("utf-8").splitlines()
with open(f, "wt") as out:
    for l in lines:
        if l.startswith("ii"):
            out.write(l.split()[1] + "\n")

Substitua f pelo caminho real do arquivo de saída.

Arquivo de saída:

...
...
apg
app-install-data
app-install-data-partner
apparmor
apport
apport-gtk
apport-retrace
apport-symptoms
appstream
apt
apt-transport-https
...
...

Nota

A solução acima criará um arquivo, terminando com uma linha vazia. Se isso for um problema, use a solução abaixo.

#!/usr/bin/env python3
import subprocess

f = "/home/jacob/Bureaublad/output.txt"

lines = subprocess.check_output(["dpkg", "-l"]).decode("utf-8").splitlines()
open(f, "wt").write(
    "\n".join([l.split()[1] for l in lines if l.startswith("ii")])
)
    
por Jacob Vlijm 09.02.2018 / 06:51
2

Observe que dpkg -l é essencialmente um frontend para dpkg-query e dpkg-query permite que você formate a saída. De man dpkg :

dpkg-query actions
  See dpkg-query(1) for more information about the following actions.

  -l, --list package-name-pattern...
      List packages matching given pattern.

E man dpkg-query :

-l, --list [package-name-pattern...]
      List  packages  matching  given  pattern.
-W, --show [package-name-pattern...]
      Just like the --list option this will list all packages matching
      the  given  pattern.  However the output can be customized using
      the --showformat option.

Então, em vez de dpkg -l , faça:

dpkg-query -f '${Package}\n' -W

'${Package}' é não uma variável de shell aqui. É um especificador de formato para dpkg-query .

    
por Olorin 09.02.2018 / 07:21
0
words=line1.split(" ")
print(words[1])

words é então uma lista de strings e as palavras [1] são as que você quer.

    
por muclux 09.02.2018 / 06:24