2011-12-25 19 views
5

ho le seguenti linee di Python:Python sottoprocesso a Bash: parentesi graffe

import subprocess 
subprocess.Popen("egrep -r --exclude=*{.git,.svn}* \"text\" ~/directory", stdout=subprocess.PIPE, shell=True).communicate()[0] 

Purtroppo, bash ignora completamente il --exclude = * {git, svn.} * bandiera.

Ho ristretto il problema alle parentesi graffe. --exclude = *. git * funzionerà attraverso il popen di Python, ma nel momento in cui vengono introdotte le parentesi graffe, sono rimasto senza aiuto. Eventuali suggerimenti?

Nota: Ho provato a fare funzionare il comando utilizzando il comando libreria di Python, produce la stessa uscita - e l'esatto stessa bandiera --exclude ignorato.

risposta

2

Direi che potrebbe essere l'escavazione della shell?

Potrebbe essere meglio suddividere gli argomenti, ed evitare completamente la shell?

import subprocess 
subprocess.Popen(["egrep","-r","--exclude=*{.git,.svn}*","text","~/directory"], stdout=subprocess.PIPE).communicate()[0] 

NB: potrebbe essere necessario espandere ~, non sono sicuro.

Oppure, se si suppone bash in espansione le parentesi allora si potrebbe farlo in python:

excludes = ['.git','.svn'] 
command = ['egrep','-r'] 
for e in excludes: 
    command.append('--exclude=*%s*'%e) 
command += ["text","~/directory"] 
subprocess.Popen(command, stdout=subprocess.PIPE).communicate()[0] 
+0

Sia questo che la shell bash funzionano bene! – user1115304

3

Quando si passa shell = True, python traduce il comando per /bin/sh -c <command> (come descritto here)./bin/sh apparentemente non supporta l'espansione delle parentesi graffe. È possibile provare il seguente invece:

import subprocess 
subprocess.Popen(["/bin/bash", "-c", "egrep -r --exclude=*{.git,.svn}* \"text\" ~/directory"], stdout=subprocess.PIPE).communicate()[0] 
+0

Sia questo che suddividere gli argomenti per evitare la shell funziona alla grande! – user1115304

0

È necessario citare questa espressione per mantenere bash da valutare contro la directory di lavoro corrente quando si spara fuori. Hai anche un bug con il tuo termine di ricerca assumendo che stai cercando "testo" (con le citazioni). La tua escaping prende le virgolette nella stringa Python ma deve essere fatta di nuovo per farle vedere alla shell.

I.e. ... --exclude='*{.git,.svn}*' \\\"text\\\" ...

0

Dal punto di vista Python Popen, opere ciò che avete wrotten, a patto di catturare l'output in una variabile Python:

import subprocess 
myOutput = subprocess.Popen("egrep -r --exclude=*{.git,.svn}* \"text\" ~/directory", stdout=subprocess.PIPE, shell=True).communicate()[0] 
print "Output: ", myOutput 

Ho testato in un terminale con la Bash come comando di default Shell, ed è funziona bene.

Si noti che 'grep -E' deve essere preferito a 'egrep', che ora è deprecato.

E sicuramente sai che \ è anche il carattere di escape per Bash, vero? Voglio dire, '*' e le parentesi graffe vengono consumate dal Bash e quindi non vengono consegnate a grep. Dovresti quindi fuggire da loro.

grep -Er --exclude=\*\{.git,.svn\}\* \"text\" ~/directory 
Problemi correlati