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).

È stato utile?

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 quotefunction è 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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top