modulo Python per shellquote / unshellquote? [duplicare]
Domanda
Questa domanda ha già una risposta qui:
- Come sfuggire os.system () chiama? 10 risposte
C'è qualcosa nella libreria standard di Python che correttamente il parsing / stringhe deanalisi per utilizzare nei comandi della shell? Sto cercando l'analogo python per String::ShellQuote::shell_quote
di Perl:
$ print String::ShellQuote::shell_quote("hello", "stack", "overflow's", "quite", "cool")
hello stack 'overflow'\''s' quite cool
E, cosa ancora più importante, qualcosa che lavorerà nella direzione inversa (prende una stringa e si decompongono in una lista).
Soluzione
pipes.quote
è ora shlex.quote
in Python 3.
E 'abbastanza facile da usare che parte del codice.
https://github.com/python/cpython/ blob / master / lib / shlex.py # L281
Questa versione gestisce argomento di lunghezza zero in modo corretto.
Altri suggerimenti
Sembra che
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"'
mi fa abbastanza lontano.
Sono abbastanza sicuro che pipes.quote è rotto, e non deve essere utilizzato, perché non gestisce correttamente gli argomenti di lunghezza zero:
>>> from pipes import quote
>>> args = ['arg1', '', 'arg3']
>>> print 'mycommand %s' % (' '.join(quote(arg) for arg in args))
mycommand arg1 arg3
Credo che il risultato dovrebbe essere qualcosa come
mycommand arg1 '' arg3
Per shell citando, questo funziona: ho rigorosamente testato su Posix. [Sto assumendo che la funzione list2cmdline
fornita da Python funziona come pubblicizzato su 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 ])
I test sono qui , se qualcuno avesse voglia.
Per unquote, provare shlex.split()
Non si dovrebbe mai avere a sborsare preventivo. Il modo corretto per eseguire un comando di non fare shell citare invece utilizzare subprocess.call o subprocess.Popen , e passare un elenco di argomenti non quotate. Questo è immune a sborsare espansione.
cioè.
subprocess.Popen(['echo', '"', '$foo'], shell=False)
Se si vuole unquote guscio citato i dati, è possibile utilizzare shlex.shlex in questo modo:
list(shlex.shlex("hello stack 'overflow'\''s' quite cool"))
Il modulo libreria sottoprocesso standard ha la funzione list2cmdline che fa questo, sebbene secondo regole di Microsoft quindi non sono sicuro di come funziona affidabile in ambienti Unix-like per le linee di comando più complicate.
Il quote
function è disponibile per un bel po 'di tempo (Python 2.7?) -. Il grave inconveniente è spostato dal modulo pipe
a shlex
tra 3,2 e 3,3
Si deve essere pronti a gestire entrambi i casi durante l'importazione che la funzione:
try:
from shlex import quote
except ImportError:
from pipes import quote