python shell quoting

Módulo de Python para shellquote/unshellquote?



quoting (8)

El subproceso del módulo de biblioteca estándar tiene la función list2cmdline que hace esto, aunque de acuerdo con las reglas de Microsoft, por lo que no estoy seguro de qué tan confiable funciona en entornos similares a Unix para líneas de comando más complicadas.

Esta pregunta ya tiene una respuesta aquí:

¿Hay algo en la biblioteca estándar de Python que analice / descomprima correctamente las cadenas para usar en los comandos de shell? Estoy buscando el análogo de python a la String::ShellQuote::shell_quote de perl String::ShellQuote::shell_quote :

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

Y, lo que es más importante, algo que funcionará en la dirección inversa (tomar una cadena y descomponerla en una lista).


Estoy bastante seguro de que pipe.quote está roto, y no debería usarse, porque no maneja correctamente los argumentos de longitud cero:

# 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 ])

Creo que el resultado debería ser algo como

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


La función de quote está disponible durante bastante tiempo (Python 2.7?). El principal inconveniente es que se movió del módulo de pipe a shlex entre 3.2 y 3.3.

Tienes que estar preparado para manejar ambos casos mientras importas esa función:

try: from shlex import quote except ImportError: from pipes import quote


Para shlex.split() , prueba shlex.split()


Para la cita de shell, esto funciona: lo he probado rigurosamente en Posix. [Supongo que la función list2cmdline proporcionada por Python funciona como se anuncia en Windows]

mycommand arg1 '''' arg3

Las pruebas están here , si a alguien le importa.


Parece

try: # py3 from shlex import quote except ImportError: # py2 from pipes import quote quote("hello ''s quite cool") >>> ''"hello /'s quite cool"''

me lleva lo suficientemente lejos.


Usted nunca debe tener que citar la cotización. La forma correcta de realizar un comando es no hacer comillas de shell y, en su lugar, utilizar subprocess.call o subprocess.Popen y pasar una lista de argumentos sin comillas. Esto es inmune a la expansión de la concha.

es decir

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

Si desea anular la cotización de los datos de la shell, puede usar shlex.shlex como este:

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