je s�che sur un probl�me que je pensait simple.
comment traiter des chaines de carat�res pour prot�ger certains
caract�res avant de les passer au shell
j'utilise Popen avec shell=True (et j'ai besoin de shell=True)
pour r�cup�rer des r�sultats de comandes externes
il se trouve qu'un cas d'utilisation me pose soucis.
les noms de fichiers � passer � mes commande comportent des
caract�res qu'il me faut prot�ger (espace, parenth�ses,
accolades et autre caract�res particuliers pour le shell)
na�vement j'ai fait une boucle pour remplacer tout caract�re non
alphanum�rique par backslash suivi de ce caract�re.
def protect_file(mmfile):
new = []
char_accepted = string.ascii_letters + string.digits +
os.path.sep
escape = '\\'
for c in mmfile:
if c in char_accepted:
new.append(c)
else:
new.append(escape + c)
return ''.join(new)
le hic, c'est que du coup j'introduit 2 backslah dans ma chaine,
celle ci etant pass�e telle qu'elle au shell. bien �videment
l'effet n'est pas du tout celui voulu ;-(
une id�e de comment m'en sortir ?
Eric
> comment traiter des chaines de caratères pour protéger certains
> caractéres avant de les passer au shell
>
> j'utilise Popen avec shell=True (et j'ai besoin de shell=True)
> pour récupérer des résultats de comandes externes
Ca aiderait de savoir quel est le shell en question. Je suppose que
c'est un shell POSIX.
Si tu entoures ta chaîne de quotes simples (d'apostrophes), il ne te
reste plus qu'à protéger les... quotes simples. Quelque chose comme :
def p(s):
return '''"'"'''.join(["'"+t+"'" for t in s.split("'")])
(pas testé).
-- Alain.
A tout hasard :
escape = '\'
le hasard ne nous r�ussi pas
Python 2.6.1 (r261:67515, Jul 7 2009, 23:51:51)
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more
information.
>>> escape = '\'
File "<stdin>", line 1
escape = '\'
^
SyntaxError: EOL while scanning string literal
>>>
J'ai test� :
from subprocess import Popen
p = Popen ("ls -l mon\ fichier", shell = True)
Ca fonctionne : il suffit donc bien d'ins�rer *un* \ devant tes
caract�res sp�ciaux.
POSIX en effet, le shell en question est sh
>
> Si tu entoures ta cha�ne de quotes simples (d'apostrophes), il ne te
> reste plus qu'� prot�ger les... quotes simples. Quelque chose comme :
>
> def p(s):
> return '''"'"'''.join(["'"+t+"'" for t in s.split("'")])
les quotes bloquent bien l'expension de carat�res "sp�ciaux" en
effet, j'avoue �tre rest� bloqu� sur le backslah.
c'est une solution que je vais tester �a de ce pas.
Eric
l� est le truc comment ins�rer *un et un seul* backslah devant
certains carat�res ?
Eric
commande = "ls -l mon" + '\\' + " fichier"
print commande
p = Popen (commande, shell = True)
ca fonctionne et affiche :
ls -l mon\ fichier
-rw-r--r-- 1 barthe barthe 0 nov 17 16:59 mon fichier
le \\ est interpr�t� comme un seul caract�re \ dans le print ainsi que
dans le Popen et la commande fonctionne.
J'ai pas test� avec les autres caract�res sp�ciaux, mais ca devrait
fonctionner de m�me.
Sur quelle commande as tu test� ta premi�re version ?
> p = Popen ("ls -l mon\ fichier", shell = True)
>
> Ca fonctionne : il suffit donc bien d'insérer *un* \ devant tes
> caractères spéciaux.
Attention : le backslash disparait seulement si il précède un caractère
spécial *pour Python*, dans les autres cas il reste en place (ce qui se
passe dans l'exemple ci-dessus). Voir
http://docs.python.org/reference/lexical_analysis.html#literals
Par exemple "un\ deux" et "un\\ deux" ont la même valeur.
-- Alain.
J'ai trouv� cette solution, mais je n'ai pas mieux :-)
>>> from subprocess import Popen
>>>
>>> escape = "\ "[0]
>>>
>>> Popen( "ls -la", shell=True)
-rw-r--r-- 1 pbouige pbouige 0 Nov 18 11:01 ( \
-rw-r--r-- 1 pbouige pbouige 0 Nov 18 11:09 ( \\
-rw-r--r-- 1 pbouige pbouige 0 Nov 18 11:00 ()
>>> comd1 = escape + '(' + escape + ' ' + escape
>>> Popen(comd1, shell=True)
<subprocess.Popen object at 0x8224e0c>
>>> -rw-r--r-- 1 pbouige pbouige 0 Nov 18 11:01 ( \
>>> comd2 = 'ls -la ' + escape + '(' + escape + ' ' + escape + escape +
escape
>>> Popen(comd2, shell=True)
<subprocess.Popen object at 0x822858c>
>>> -rw-r--r-- 1 pbouige pbouige 0 Nov 18 11:09 ( \\
autre exemple :
touch '( &'
-rw-r--r-- 1 pbouige pbouige 0 Nov 18 11:22 ( &
sous python :
>>> from subprocess import Popen
>>>
>>> escape = '\ '[0]
>>>
>>> cmd3 = 'ls -la ' + escape + '(' + escape + ' ' + escape + '&'
>>> Popen(cmd3, shell=True)
<subprocess.Popen object at 0x8224eac>
>>> -rw-r--r-- 1 pbouige pbouige 0 Nov 18 11:22 ( &
merci.
tout simple. une solution �l�gante.
Eric