Python módulo para shellquote / unshellquote? [duplicado]
Pergunta
Esta questão já tem uma resposta aqui:
- Como escapar os.system () chamadas? 10 respostas
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).
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 quote
function 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