36

Python 标准库中是否有任何东西可以正确解析/解析字符串以在 shell 命令中使用?我正在寻找 perl 的 python 模拟String::ShellQuote::shell_quote

$ print String::ShellQuote::shell_quote("hello", "stack", "overflow's", "quite", "cool")
hello stack 'overflow'\''s' quite cool

而且,更重要的是,一些可以反向工作的东西(取一个字符串并将其分解为一个列表)。

4

8 回答 8

32

好像

try:  # py3
    from shlex import quote
except ImportError:  # py2
    from pipes import quote

quote("hello stack overflow's quite cool")
>>> '"hello stack overflow\'s quite cool"'

让我够远。

于 2009-07-01T18:57:34.513 回答
10

pipes.quote现在shlex.quote在 python 3 中。使用那段代码很容易。

https://github.com/python/cpython/blob/master/Lib/shlex.py#L281

该版本正确处理零长度参数。

于 2014-08-05T20:19:03.983 回答
7

要取消报价,请尝试 shlex.split()

于 2011-01-26T14:14:53.120 回答
7

我很确定 pipe.quote 已损坏,不应使用,因为它不能正确处理零长度参数:

>>> from pipes import quote
>>> args = ['arg1', '', 'arg3']
>>> print 'mycommand %s' % (' '.join(quote(arg) for arg in args))
mycommand arg1  arg3

我相信结果应该是这样的

mycommand arg1 '' arg3
于 2009-12-10T23:07:40.893 回答
6

对于 shell 引用,这是可行的:我已经在 Posix 上对其进行了严格测试。[我假设list2cmdlinePython 提供的函数按照 Windows 上宣传的那样工作]

# shell.py
import os
if os.name == 'nt':
    from subprocess import list2cmdline

    def quote(arg):
        return list2cmdline([arg])[0]
else:
    import re
    _quote_pos = re.compile('(?=[^-0-9a-zA-Z_./\n])')

    def quote(arg):
        r"""
        >>> quote('\t')
        '\\\t'
        >>> quote('foo bar')
        'foo\\ bar'
        """
        # This is the logic emacs uses
        if arg:
            return _quote_pos.sub('\\\\', arg).replace('\n',"'\n'")
        else:
            return "''"

    def list2cmdline(args):
        return ' '.join([ quote(a) for a in args ])

测试就在这里,如果有人在乎的话。

于 2011-07-31T17:20:07.163 回答
2

quote函数在相当长的一段时间内可用(Python 2.7?)——主要缺点是它从pipe模块移动到shlex3.2 和 3.3 之间。

在导入该函数时,您必须准备好处理这两种情况:

try:
    from shlex import quote
except ImportError:
    from pipes import quote
于 2014-08-08T17:08:37.743 回答
2

标准库模块子进程具有执行此操作的 list2cmdline 函数,尽管根据Microsoft 规则,所以我不确定它在类 Unix 环境中对于更复杂的命令行的工作可靠性如何。

于 2011-01-10T17:18:55.707 回答
0

您永远不必壳报价。执行命令的正确方法是不执行 shell 引用,而是使用subprocess.callsubprocess.Popen,并传递未引用参数的列表。这不受壳膨胀的影响。

IE

subprocess.Popen(['echo', '"', '$foo'], shell=False)

如果要取消引用 shell 引用的数据,可以像这样使用shlex.shlex

list(shlex.shlex("hello stack 'overflow'\''s' quite cool"))
于 2009-06-08T23:02:40.513 回答