module Python à shellquote / unshellquote? [dupliquer]
Question
Cette question a déjà une réponse ici:
- Comment échapper os.system () appelle 10 réponses
Y at-il dans la bibliothèque standard de Python qui analyser correctement les chaînes / unparse pour l'utilisation dans les commandes shell? Je cherche l'analogue python au String::ShellQuote::shell_quote
de perl:
$ print String::ShellQuote::shell_quote("hello", "stack", "overflow's", "quite", "cool")
hello stack 'overflow'\''s' quite cool
Et, plus important encore, quelque chose qui va travailler dans le sens inverse (une chaîne de caractères et le décomposer en une liste).
La solution
pipes.quote
est maintenant shlex.quote
en python 3.
Il est assez facile d'utiliser ce morceau de code.
https://github.com/python/cpython/ blob / maître / Lib / shlex.py # L281
Cette version gère correctement l'argument zéro longueur.
Autres conseils
On dirait
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 reçoit assez.
Je suis assez sûr que pipes.quote est cassé, et ne doit pas être utilisé, car il ne gère pas correctement des arguments zéro longueur:
>>> from pipes import quote
>>> args = ['arg1', '', 'arg3']
>>> print 'mycommand %s' % (' '.join(quote(arg) for arg in args))
mycommand arg1 arg3
Je crois que le résultat devrait être quelque chose comme
mycommand arg1 '' arg3
Pour le shell de citer, cela fonctionne: je l'ai rigoureusement testé sur Posix. [Je suppose que la fonction list2cmdline
fourni par Python fonctionne comme prévu sur 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 ])
Pour CITATION, essayez shlex.split()
Vous ne devriez jamais avoir à débourser devis. La bonne façon de faire une commande est de ne pas faire shell citer et d'utiliser plutôt subprocess.call ou subprocess.Popen , et transmettre une liste des arguments non cotées. Ceci est à l'abri de l'expansion du shell.
i.e..
subprocess.Popen(['echo', '"', '$foo'], shell=False)
Si vous voulez CITATION données cité shell, vous pouvez utiliser shlex.shlex comme ceci:
list(shlex.shlex("hello stack 'overflow'\''s' quite cool"))
Le module de bibliothèque standard de sous-processus a pour fonction de list2cmdline qui fait cela, bien que selon la règles Microsoft donc je ne sais pas comment cela fonctionne fiable dans les environnements Unix pour les lignes de commande plus complexes.
Le quote
function est disponible depuis un certain temps (Python 2.7?) -. L'inconvénient majeur est déplacé du module il de pipe
à shlex
entre 3,2 et 3,3
Vous devez être prêt à gérer les deux cas, lors de l'importation de cette fonction:
try:
from shlex import quote
except ImportError:
from pipes import quote