Подпроцесс Python для Bash: фигурные скобки - PullRequest
5 голосов
/ 25 декабря 2011

У меня есть следующие строки Python:

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

К сожалению, bash полностью игнорирует флаг - exclude = * {. Git, .svn} *.

Я сузил проблему до фигурных скобок.--exclude = *. git * будет работать через всплывающие окна Python, но как только появятся фигурные скобки, я останусь беспомощным.Любые предложения?

Примечание. Я попытался запустить команду, используя библиотеку Python command , она выдает точно такой же вывод - и тот же игнорируемый флаг --exclude.

Ответы [ 4 ]

3 голосов
/ 25 декабря 2011

Когда вы передаете shell = True, python переводит команду в /bin/sh -c <command> (как описано здесь ). / bin / sh, по-видимому, не поддерживает расширение фигурных скобок. Вместо этого вы можете попробовать следующее:

import subprocess
subprocess.Popen(["/bin/bash", "-c", "egrep -r --exclude=*{.git,.svn}* \"text\" ~/directory"], stdout=subprocess.PIPE).communicate()[0]
2 голосов
/ 25 декабря 2011

Я предполагаю, что это может быть экранирование оболочки?

Может быть, лучше разбить аргументы самостоятельно и полностью избежать оболочки?

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

NB. Возможно, вам придется расширить ~, я не уверен.

Или, если предполагается, что bash расширяет скобки, вы можете сделать это на 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 голосов
/ 25 декабря 2011

С точки зрения Python Popen все, что у вас есть, работает, при условии, что вы захватили вывод в переменную Python:

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

Я проверил в терминале команду Bash по умолчанию, и онаработает хорошо.

Обратите внимание, что 'grep -E' следует отдавать предпочтение 'egrep', которое сейчас устарело.

И вы наверняка знаете, что \ также является escape-символом для Bashне так ли?Я имею в виду, что '*' и фигурные скобки потребляются Bash, и поэтому не передаются grep.Поэтому вам следует избегать их.

grep -Er --exclude=\*\{.git,.svn\}\* \"text\" ~/directory
0 голосов
/ 25 декабря 2011

Вам нужно заключить это выражение в кавычки, чтобы bash не сравнивал его с вашим текущим рабочим каталогом при его запуске.У вас также есть ошибка с вашим поисковым термином, если вы ищете «текст» (с цитатами).Ваше экранирование получает кавычки в строку Python, но необходимо сделать это снова, чтобы оболочка увидела их.

Т.е. ... --exclude='*{.git,.svn}*' \\\"text\\\" ...

...