Pergunta

Esta questão já tem uma resposta aqui:

Existe alguma coisa na biblioteca padrão Python que irá analisar corretamente / cordas unparse para uso em comandos shell? Eu estou olhando para o analógico python para String::ShellQuote::shell_quote do Perl:

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

E, ainda mais importante, algo que irá funcionar no sentido inverso (tomar uma corda e decompô-la em uma lista).

Foi útil?

Solução

pipes.quote está agora shlex.quote em python 3. É bastante fácil de usar esse pedaço de código.

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

Isso alças versão argumento de comprimento zero corretamente.

Outras dicas

Looks como

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"'

me deixa longe o suficiente.

Eu tenho certeza que pipes.quote está quebrado, e não deve ser usado, porque não lidar com argumentos de comprimento zero corretamente:

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

Eu acredito que o resultado deve ser algo como

mycommand arg1 '' arg3

Para shell citando, isso funciona: Eu rigorosamente testado-lo em POSIX. [Estou assumindo que a função list2cmdline fornecido pelo Python funciona como anunciado no 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 ])

Os testes são aqui , se cuidados ninguém.

Para unquote, tente shlex.split()

Você nunca deve ter que desembolsar cotação. A maneira correta de fazer um comando é a de não fazer shell citando e passar a usar subprocess.call ou subprocess.Popen , e passar uma lista de argumentos não cotadas. Esta é imune a expansão shell.

i.

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

Se você quiser dados shell citado unquote, você pode usar shlex.shlex assim:

list(shlex.shlex("hello stack 'overflow'\''s' quite cool"))

O padrão módulo de biblioteca subprocess tem a função list2cmdline que faz isso, ainda de acordo com a regras Microsoft por isso não estou certo de quão confiável ele funciona em Unix-like ambientes para linhas de comando mais complicado.

O quotefunction está disponível por algum tempo (Python 2,7?) -. A principal desvantagem é que movido a partir do módulo pipe para shlex entre 3,2 e 3,3

Você tem que estar preparado para lidar com ambos os casos durante a importação essa função:

try:
    from shlex import quote
except ImportError:
    from pipes import quote
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top