Entre deux réveillons (que je vous souhaite des plus agréables), j'ai
quelques difficultés avec les variables composées, c'est-à-dire dont le
nom est le résultat de plusieurs paramètres. Un exemple :
set x un
set y deux
set undeux 12
Je veux récupérer $undeux depuis x et y. La seule solution que j'ai
trouvée :
puts "[subst $$x[subst $y]]"
Ne peut-on faire plus simple avec des (), {} ou autres ?
Dans le cas d'un array, si je veux récupérer $winX_docked($win), avec
set suffix _docked, je me trouve à écrire :
[subst $[subst winX$suffix]($win) ]
N'y a-t-il pas plus court ou lisible ?
Pascal Georges
Plus court oui, plus lisible, à voir ...
set x un
set y deux
set undeux 12
puts [set $x$y]
Avec un array cela devrait donner (non testé)
puts [set winX$suffix($win)]
--
Jack.R
puts [set $x$y]
Pour l'autre cas, le troisième alinéa de la règle 7 (voir http://wfr.tcl.tk/38)
répond à ta question : tu peux fixer le nom de la variable avec des
accolades. Dans ton cas, ça donne :
puts [set winX${suffix}($win)]
Mais :
Si tu en arrives à avoir ces noms de variables, c'est que tu
n'utilises probablement pas le bon type de variable pour stocker tes
données. Je pense que tu devrais jeter un coup d'oeil à http://wfr.tcl.tk/dict
qui devrait t'apporter la souplesse dont tu sembles avoir besoin.
--
David Zolli
Pour le premier cas, ça donnerait :
% set x un
% set y deux
% dict set dico "$x $y" 12 ; # enregistre la valeur
% dict get $dico "$x $y" ; # lit la valeur enregistrée
12
Pour le deuxième cas :
% set win .fen
% set suffix docked
% dict set winX "$win $suffix" true
% dict get $winX "$win $suffix"
true
Ulis n'est plus là pour me remonter les bretelles, mais j'ai
volontairement utilisé des guillemets dans ces exemples pour que ça
soit plus facile à comprendre. La syntaxe idéale étant :
% dict set winX [list $win $suffix] true
Quant à [subst], il est très dangereux, comme le montre l'exemple
suivant (à ne surtout pas essayer !) :
set var {Je vais effacer tes données : [file delete -force ~]}
puts [subst {Vous avez entré la valeur $var.}]
On voit bien les dégâts que peut provoquer subst avec des variables
entrées par un utilisateurs sournois / idiot / malchanceux. En
particulier quand elles contiennent des crochets...
--
David Zolli
P.S.
Une solution simple pour se protéger contre ça c'est d'utiliser le
plus possible [subst -nocommands ...] plutôt que [subst ...] tout
seul.
--
David Zolli
Kroc a écrit :
> On 29 déc, 17:21, I wrote:
>> Quant à [subst], il est très dangereux, comme le montre l'exemple
>> suivant (à ne surtout pas essayer !) :
>> ...
> Une solution simple pour se protéger contre ça c'est d'utiliser le
> plus possible [subst -nocommands ...] plutôt que [subst ...] tout
> seul.
Que neni, helas!
% set var "code inclusion perverse \$tcl_platform(os\[puts AIE!\])"
% puts [subst -nocommand $var]
Et un beau "AIE!" qui apparait a l'ecran. Bien sur, un "file delete
-force ~" et autre [exec ...] encore plus destructeur sont possible a la
place du [puts], mais je ne voudrais pas que quelqu'un fasse un
copier-coller du code sans lire auparavant l'avertissement "SURTOUT NE
PAS EXECUTER".
Pour moi, ca s'apparente plus a un "bug" qu'a un "feature", mais
d'autre, dans d'autres discussions passees, pensaient differemment.
En tout cas, ce qu'il faut retenir: [subst -nocommand] ne PROTEGE PAS de
l'inclusion de code dangereux (ou pas) lors de la substitution. Donc si
la valeur de la chaine a substituer ne vient pas d'une source de
confiance (par ex. un formulaire web, etc...); revoyez tous vos code a
coup de "grep" pour reperer les [subst -nocommand] qui ne vous protege
pas malgre ce que le nom de l'option laisse penser.
Puis j'en profite:
Bonnes fetes a tous, que 2009 soit une annee pleine de bonheur et
Tcleusement votre.
Eric
-----
Eric Hassold
Evolane - http://www.evolane.com/
>
> --
> David Zolli
Merci pour vos précisions, j'y vois plus clair. Seul détail, pourquoi
set x un
set y deux
set undeux 12
puts "$${x}${y}"
renvoit $undeux et non pas 12 ?
et là il est interdit d'utiliser une deuxième couche de {} comme :
puts "${${x}${y}}"
mais il est vrai que [set ...] fait bien le travail demandé, et mon code
fait "plus propre".
Pascal Georges
> En tout cas, ce qu'il faut retenir: [subst -nocommand] ne PROTEGE PAS de
> l'inclusion de code dangereux (ou pas) lors de la substitution.
Eric, ce n'est pas la première fois que tu parles de ce risque... mais
ce n'est que maintenant que je comprends !
J'ai maintenant d'autres raisons que la lisibilité d'éviter "subst".
Pascal
De rien.
> Seul détail, pourquoi
>
> set x un
> set y deux
> set undeux 12
> puts "$${x}${y}"
>
> renvoit $undeux et non pas 12 ?
Pour bien comprendre, on va se transformer en interpréteur Tcl en se
basant sur les douze règles (http://wfr.tcl.tk/38 qui est encore à 11
le temps de transformer la 5 bis) et analyser la ligne :
puts $${x}${y}
Selon la règle 1, on a une commande qui se termine par un retour à la
ligne.
Selon les règles 2 et 3, notre commande est composée de 2 mots, le
premier étant notre commande (puts) le reste étant les arguments de
cette commande.
Je garde "puts" et il me reste à interpréter $${x}${y}
Les règles 4, 5, 5bis et 6 ne s'appliquent pas à notre deuxième mot.
Selon la règle 7, Si un mot contient un symbole dollar («$») alors TCL
exécute une substitution de variable : le symbole dollar et les
caractères suivants seront remplacés dans le mot par la valeur d'une
variable. Mais selon la règle 10, chaque caractère est traité
exactement une seule fois par l'interprèteur TCL en tant qu'élément de
création des mots d'une commande et les substitutions ont lieu de
gauche à droite et chaque substitution est évaluée complètement avant
d'essayer d'évaluer la suivante. Si on applique tout ça à notre mot $$
{x}${y} ça donne :
Je trouve un $ en première position, selon la règle 7 alinéa 1, je
prend un ou plusieurs caractères qui peuvent être une lettre, un
chiffre, un souligné, ou des séparateurs d'espace de noms qui suivent
ce $ comme nom de variable. Dans mon cas, le deuxième caractère est un
$ donc mon nom de variable est vide {} : je ne remplace pas mon dollar
puisqu'il ne représente pas une variable :
Je garde "puts $" et il me reste à interpréter ${x}${y}
Je trouve encore un dollar en première position, suivi d'une accolade,
selon la règle 7 alinéa 3, je doit donc remplacer ${x} par sa valeur :
un
Je garde "puts $un" et il me reste à interpréter ${y}
Je trouve encore un dollar en première position, suivi d'une accolade,
selon la règle 7 alinéa 3, je doit donc remplacer ${y} par sa valeur :
deux
Je garde "puts $undeux" et il me reste rien à interpréter : ma
commande est effectué et $undeux est affiché.
CQFD
> et là il est interdit d'utiliser une deuxième couche de {} comme :
> puts "${${x}${y}}"
Oui, car selon la règle 5, aucune substitution de variable n'a lieu à
l'intérieur d'accolades.
> mais il est vrai que [set ...] fait bien le travail demandé, et mon code
> fait "plus propre".
En effet, puisque l'interpréteur rencontre un crochet, selon la règle
6, on doit traiter le contenu de ce crochet récursivement, ce qui
donne :
1) puts [set $x$y] qui devient puts [set undeux]
2) puts [set undeux] qui devient puts 12
En espérant avoir été clair.
--
David Zolli
Mais c'est très fourbe cette astuce de la parenthèse !!
> Et un beau "AIE!" qui apparait a l'ecran. Bien sur, un "file delete
> -force ~" et autre [exec ...] encore plus destructeur sont possible a la
> place du [puts], mais je ne voudrais pas que quelqu'un fasse un
> copier-coller du code sans lire auparavant l'avertissement "SURTOUT NE
> PAS EXECUTER".
Ah oui, j'ai pas été assez prudent sur ce coup :^/
> Pour moi, ca s'apparente plus a un "bug" qu'a un "feature", mais
> d'autre, dans d'autres discussions passees, pensaient differemment.
Si ça c'est pas un bug, je serais assez curieux de lire quelle
justification débile on a trouvé à te répondre (et qui défend ça).
D'autant qu'aucune limitation n'est donnée dans la documentation à ce
sujet !
--
David Zolli
A force de copicollages entre "on doit" et "je dois" ça a fini sur un
mauvais mélange, désolé. :-(
--
David Zolli
Extrêmement clair.
Merci.
Pascal Georges.