如何反转shlex.split
的结果?也就是说,如果我希望引用list
字符串,我如何获得"resemble that of a Unix shell"的带引号的字符串?
我找到了一个Python错误,并提出了相应的功能请求here。
答案 0 :(得分:26)
我们现在(3.3)具有shlex.quote功能。 pipes.quote
已移动并记录(使用pipes.quote
的代码仍然有效)。有关整个讨论,请参阅http://bugs.python.org/issue9723。
subprocess.list2cmdline
是一个不应该使用的私有函数。然而,它可以移至shlex
并正式公开。另请参阅http://bugs.python.org/issue1724822。
答案 1 :(得分:19)
如何使用pipes.quote
?
import pipes
strings = ["ls", "/etc/services", "file with spaces"]
" ".join(pipes.quote(s) for s in strings)
# "ls /etc/services 'file with spaces'"
答案 2 :(得分:6)
subprocess
使用subprocess.list2cmdline()
。它不是官方的公共API,但它在subprocess
文档中提到过,我认为使用它非常安全。它比pipes.open()
更复杂(无论好坏)。
答案 3 :(得分:2)
有一项添加shlex.join()
的功能请求,可以完全按照您的要求进行操作。截至目前,似乎没有任何进展,主要是因为它主要只是前进到shlex.quote()
。在错误报告中,提到了一个建议的实现:
' '.join(shlex.quote(x) for x in split_command)
答案 4 :(得分:0)
它是python 3.8中的shlex.join()
答案 5 :(得分:0)
虽然 shlex.quote 在 Python 3.3 中可用,shlex.join 在 Python 3.8 中可用,但它们并不总是作为 shlex.split
的真正“反转”。观察以下片段:
import shlex
command = "cd /home && bash -c 'echo $HOME'"
print(shlex.split(command))
# ['cd', '/home', '&&', 'bash', '-c', 'echo $HOME']
print(shlex.join(shlex.split(command)))
# cd /home '&&' bash -c 'echo $HOME'
请注意,在拆分然后加入之后,&&
标记现在周围有单引号。如果您现在尝试运行该命令,则会出现错误:cd: too many arguments
如果您按照其他人的建议使用 subprocess.list2cmdline()
,那么它与 &&
之类的 bash 运算符一起使用效果更好:
import subprocess
print(subprocess.list2cmdline(shlex.split(command)))
# cd /home && bash -c "echo $HOME"
但是您现在可能会注意到引号现在是双引号而不是单引号。这会导致 $HOME
被 shell 展开,而不是像使用单引号一样逐字打印。
总而言之,撤销 shlex.split
没有 100% 万无一失的方法,您必须选择最适合您的目的的选项并注意边缘情况。