84 votes

Comment utiliser des variables dans une boucle for bash

Comment utiliser une variable dans une boucle for bash ? Si j'utilise une boucle for standard, elle fait ce que j'attends.

for i in {0..3}
do
   echo "do some stuff $i"
done

Cela fonctionne bien. Il boucle 4 fois, de 0 à 3 inclus, en imprimant mon message et en plaçant le compte à la fin.

do some stuff 0
do some stuff 1
do some stuff 2
do some stuff 3

Lorsque j'essaie la même chose avec la boucle for suivante, il semble que le résultat soit égal à une chaîne de caractères, ce qui n'est pas ce que je veux.

length=3
for i in {0..$length}
do
   echo "do something right $i"
done

de la production :

do something right {0..3}

J'ai essayé

for i in {0.."$length"} and for i in {0..${length}} (both output was {0..3})

et

for i in {0..'$length'} (output was {0..$length})

et tous deux ne font pas ce dont j'ai besoin. J'espère que quelqu'un pourra m'aider. Merci d'avance à tout expert de bash pour son aide sur les boucles for.

137voto

perreal Points 47912

L'une des méthodes consiste à utiliser eval :

for i in $( eval echo {0..$length} )
do
       echo "do something right $i"
done

Note que se passe-t-il lorsque l'on fixe length=;ls o length=; rm * (n'essayez pas cette dernière solution).

en toute sécurité , en utilisant seq :

for i in $( seq 0 $length )
do
       echo "do something right $i"
done

ou vous pouvez utiliser la boucle for de style c, qui est également sûre :

for (( i = 0; i <= $length; i++ )) 
do 
       echo "do something right $i"
done

17voto

paxdiablo Points 341644

En bash, l'expansion des accolades est la fonction premier a tenté de le faire, à ce moment-là, $length n'aura pas été remplacé.

La page de manuel de bash l'indique clairement :

Une expression de séquence se présente sous la forme {x..y[..incr]}, où x et y sont soit des nombres entiers, soit des caractères simples ...

Il existe un certain nombre de possibilités, telles que l'utilisation :

pax> for i in $(seq 0 $length) ; do echo $i ; done
0
1
2
3

bien que cela puisse vous donner une ligne de commande volumineuse si length est massif.

Une autre solution consiste à utiliser la syntaxe de type C :

pax> for (( i = 0; i <= $length; i++ )) ; do echo $i; done
0
1
2
3

Il est également possible d'omettre $ s'inscrire double parenthèse pour faire référence à une variable :

ubuntu@ip-172-31-28-53:~/playground$ length=3;
ubuntu@ip-172-31-28-53:~/playground$ for ((i=0;i<=length;i++));do echo $i;done
0
1
2
3

9voto

nemo Points 13983

Les sous-titutions Brace sont effectuées avant toute autre, vous devez donc utiliser la fonction eval ou un outil tiers comme seq .

Exemple pour l'évaluation :

for i in `eval echo {0..$length}`; do echo $i; done

Cette information peut être trouvée dans man bash :

Une expression de séquence se présente sous la forme {x..y[..incr]}, où x et y sont soit des entiers ou des caractères simples et incr, un incrément optionnel, i [...]

L'expansion de l'accolade est effectuée avant toutes les autres expansions, et tous les caractères spéciaux aux autres expansions sont conservés dans le résultat. Elle est strictement textuelle. Bash n'applique aucune interprétation syntaxique au contexte de l'expansion ni au texte entre les accolades.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X