Parcours des arguments du premier au dernier
Dans les interpréteurs de commandes du type bash, les paramètres positionnels
du script ou d'une fonction peuvent être obtenus individuellement à l'aide des
variables affectées automatiquement par l'interpréteur : $1
(pour le premier
arguments), $2
pour le deuxième, $3
, etc.
Mais pour parcourir successivement un à un les paramètres positionnels passés à
un script ou une fonction shell, on peut simplement utiliser une boucle for
de ce genre :
1 for
2 do
3 ;
4 done
Cela fonctionne car, utilisé sans le mot-clef in
, for
effectue par défaut
une boucle sur tous les paramètres positionnels, ce qui revient donc au même
que d'utiliser for arg in "$@"
(qui fonctionne aussi, et qui a d'ailleurs le
mérite d'être plus explicite, "$@"
étant remplacé par la liste des arguments
positionnels).
Parcours des arguments du dernier au premier
Pour parcourir la liste de ces paramètres à l'envers (c'est à dire du dernier
au premier paramètre positionel), on doit avoir recours à l'utilisation de la
fonction interne du shell eval
:
1 for
2 do
3 arg=""
4
5 done
for
effectue ici une boucle sur les numéros de paramètres qu'on veut traiter,
du dernier paramètre, fourni par la variable automatique $#
, au premier,
numéroté 1
($0
n'est pas un paramètre, mais le nom du script).
Ensuite, pour lire la valeur du paramètre positionnel de numéro $i
(c'est à
dire $4
, $3
, …), on utilise eval
à la ligne 3 pour exécuter la commande
echo \$$i
.
Pour bien comprendre cette ligne 3, notez bien que :
- la commande fournie à
eval
est évaluée deux fois : une fois lors de l'exécution normale du script, puis le résultat de cette première évaluation sera évalué par la fonctioneval
elle-même ; - il faut donc déspécialiser le premier
$
à l'aide d'une barre oblique inverse pour que la première évaluation ne l'interprète pas et le conserve tel quel ; - lors de la seconde évalution, ce premier
$
sera cette fois utilisé en conjonction avec le chiffre obtenu par l'évaluation du$i
qui le suit :eval
va donc exécuter une fonction qui ressemblera àecho $3
(le chiffre changeant bien sûr en fonction de la valeur dei
) et en renverra le résulat.
Alternative spécifique à l'interpréteur bash
Avec l'interpréteur bash, parcourir la liste de ces paramètres à l'envers peut
être réalisé sans avoir recours à eval
, grâce au mécanisme de développement
indirect spécifique à bash :
1 for
2 do
3 arg=
4 ;
5 done
Attention : ces indirections de variables n'existent pas dans la norme POSIX (norme IEEE 1003.1) et sont donc spécifiques à l'interpréteur bash. Elles ne fonctionneront pas avec les interpréteurs se limitant à cette norme (ce qui est par exemple généralement le cas lorsque vous utilisez l'interpréteur simplement nommé sh).
Ici, pour lire la valeur du paramètre positionnel (contenue dans $4
, $3
,
...), on introduit un niveau d'indirection de variable grâce au point
d'exclamation : il indique qu'on veut lire la valeur d'une variable dont le nom
est contenu dans une autre variable.
Ainsi, si $i
contient 3
, ${!i}
sera remplacé par la valeur de la variable
$3
, donc le troisième argument positionnel du script ou de la fonction, tout
comme le ferait la commande eval "echo \$$i"
.
Corollaire : grâce à ce mécanisme de développement indirect de bash, le
dernier paramètre positinel d'un script ou d'une fonction bash peut donc être
obtenu directement grâce à l'expression ${!#}
que vous devriez maintenant
pouvoir comprendre correctement.
Notez qu'on a recours à la commande seq
plutôt qu'au générateur de série
interne de bash (du type {10..1}
) car ce dernier utilise les accolades qui
sont évaluées avant le remplacement des variables. On ne peut donc pas
écrire quelque chose comme {$#..1}
pour obtenir la série de chiffres entre
le dernier et le premier argument positionnel.