módulo de Python para shellquote / unshellquote? [duplicar]
Pregunta
Esta pregunta ya tiene una respuesta aquí:
- Cómo escapar os.system () llama? 10 respuestas
¿Hay algo en la biblioteca estándar de Python que analizar adecuadamente / cuerdas unparse para usar en comandos shell? Busco el análogo de pitón a String::ShellQuote::shell_quote
de Perl:
$ print String::ShellQuote::shell_quote("hello", "stack", "overflow's", "quite", "cool")
hello stack 'overflow'\''s' quite cool
Y, aún más importante, algo que va a trabajar en la dirección inversa (tomar una cadena y se descomponen en una lista).
Solución
pipes.quote
está ahora shlex.quote
en Python 3.
Es bastante fácil de usar ese pedazo de código.
https://github.com/python/cpython/ blob / maestro / lib / shlex.py # L281
Esa versión maneja el argumento de longitud cero correctamente.
Otros consejos
Parece
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 molesta lo suficiente.
Estoy bastante seguro de que pipes.quote se rompe, y no debe ser utilizado, ya que no se ocupa de argumentos de longitud cero correctamente:
>>> from pipes import quote
>>> args = ['arg1', '', 'arg3']
>>> print 'mycommand %s' % (' '.join(quote(arg) for arg in args))
mycommand arg1 arg3
Creo que el resultado debería ser algo así como
mycommand arg1 '' arg3
Para citar cáscara, esto funciona: rigurosamente que he probado en POSIX. [Estoy asumiendo que la función list2cmdline
suministrada por Python funciona como se anuncia en 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 ])
Las pruebas son aquí , si a alguien le interesa.
A fin de la cita, trate shlex.split()
Usted debe nunca tener que pagar cotización. La forma correcta de hacer una orden es no hacer la cáscara citando y en su lugar utilizar subprocess.call o subprocess.Popen , y pasar una lista de argumentos no cotizados. Este es inmune a la cabeza de expansión.
es decir.
subprocess.Popen(['echo', '"', '$foo'], shell=False)
Si desea Unquote cáscara citó datos, puede utilizar shlex.shlex como esto:
list(shlex.shlex("hello stack 'overflow'\''s' quite cool"))
El subproceso módulo de biblioteca estándar tiene la función list2cmdline que hace esto, aunque de acuerdo con reglas de Microsoft así que no estoy seguro de cómo funciona fiable en entornos Unix para las líneas de comandos más complicados.
El quote
function está disponible desde hace bastante tiempo (Python 2.7?) -. El mayor inconveniente es que se movió desde el módulo pipe
a shlex
entre 3,2 y 3,3
Usted tiene que estar preparado para manejar ambos casos, mientras que la importación de esa función:
try:
from shlex import quote
except ImportError:
from pipes import quote