简体   繁体   English

Bash的Python子流程:花括号

[英]Python subprocess to Bash: curly braces

I have the following Python lines: 我有以下Python行:

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

Unfortunately, bash completely ignores the --exclude=*{.git,.svn}* flag. 不幸的是,bash完全忽略了--exclude = * {。git,.svn} *标志。

I've narrowed down the problem to the curly braces. 我已将问题缩小为花括号。 --exclude=*.git* will work through python's popen, but the moment curly braces are introduced, I'm left helpless. --exclude = *。git *将在python的popen中起作用,但是一旦引入了花括号,我就束手无策了。 Any suggestions? 有什么建议么?

Note: I tried running the command using Python's command library, it produces the exact same output -- and the exact same ignored --exclude flag. 注意:我尝试使用Python的命令库运行命令,它会产生完全相同的输出-和完全相同的忽略-exclude标志。

When you pass shell=True, python translates the command to /bin/sh -c <command> (as described here ). 当传递壳=真,蟒转换命令到/bin/sh -c <command> (如所描述的在这里 )。 /bin/sh apparently does not support the curly braces expansion. / bin / sh显然不支持花括号扩展。 You can try the following instead: 您可以尝试以下方法:

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

I would guess that it might be shell escaping? 我想这可能是外壳转义?

It might be best to do your own splitting up of the arguments, and avoid the shell entirely? 最好自行分解参数,并完全避免使用shell?

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

NB: You might have to expand ~ , I'm not sure. 注意:您可能需要扩展~ ,我不确定。

Or if bash is supposed to be expanding the braces then you could do it in python: 或者如果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]

You need to quote that expression to keep bash from evaluating it against your current working directory when you fire it off. 您需要引用该表达式,以防止bash在启动时针对当前工作目录对其进行评估。 You also have a bug with your search term assuming you are looking for "text" (with the quotations). 假设您要查找“文本”(带引号),则搜索词也会出现错误。 Your escaping gets the quotes into the Python string but needs to be done again to have the shell see them. 您的转义将引号添加到Python字符串中,但需要再次执行以使Shell看到引号。

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

From a Python Popen perspective, what you have wrotten works, provided you capture the output in a Python variable: 从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

I have tested in a terminal with the Bash as default Shell command, and it works well. 我已经在Bash作为默认Shell命令的终端中进行了测试,并且效果很好。

Note that 'grep -E' should be preferred to 'egrep', which is now deprecated. 请注意,“ grep -E”应优先于“ egrep”,后者已被弃用。

And you certainly know that \\ is also the escape character for the Bash, don't you? 而且您当然知道\\也是Bash的转义字符,不是吗? I mean, '*' and the curly braces are consumed by the Bash, and are therefore not handed over to grep. 我的意思是,'*'和花括号被Bash占用,因此不会移交给grep。 You should therefore escape them. 因此,您应该逃脱它们。

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

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

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