Python 子进程:无法转义引号

Chr*_*ers 2 python bash shell quotes subprocess

我知道以前曾问过类似的问题,但它们似乎都是通过重新设计参数的传递方式(即使用列表等)来解决的。

但是,我这里有一个问题,因为我没有这个选项。有一个特定的命令行程序(我使用的是 Bash shell),我必须向其传递带引号的字符串。它不能不被引用,也不能有重复的参数,它只能是单引号或双引号。

command -flag 'foo foo1'
Run Code Online (Sandbox Code Playgroud)

我不会用command -flag foo foo1,也不会用command -flag foo -flag foo1。我认为这是命令接收输入方式的疏忽,但我无法控制它。

我传递参数如下:

self.commands = [
                self.path,
                '-flag1', quoted_argument,
                '-flag2', 'test',
                ...etc...
                ]
process = subprocess.Popen(self.commands, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
results = process.communicate(input)
Run Code Online (Sandbox Code Playgroud)

哪里quoted_argument有像“foo foo1 foo2”这样的东西。我尝试转义单引号 ( "\'foo foo1 foo2\'"),但没有得到任何输出。

我知道这被认为是不好的做法,因为它解释起来不明确,但我没有其他选择。有任何想法吗?

tde*_*ney 8

shell 将命令字符串分解为列表。引号告诉 shell 将多个单词放入单个列表项中。由于您是自己构建列表,因此您可以将单词添加为单个项目(不带引号)。

这两个Popen命令是等价的

Popen("command -flag 'foo foo1'", shell=True)
Popen(["command", "-flag", "foo foo1"])
Run Code Online (Sandbox Code Playgroud)

编辑

这个答案涉及 shell 中的转义字符。如果您不使用 shell,则无需添加任何引号或转义符,只需放入字符串本身。跳过 shell 还存在其他问题,例如管道命令、运行后台作业、使用 shell 变量等。这些都可以在 python 而不是 shell 中完成。

  • 注意:第一个“Popen()”调用运行一个中间 shell 进程。第二个*在启动“命令”之前不运行 shell*。 (3认同)