web-dev-qa-db-fra.com

Utilisation d'une variable dans la plage d'expansion de l'entretoise alimentée à une boucle for

Voici myscript.sh

#!/bin/bash
for i in {1..$1};
do
    echo $1 $i;
done

Si je lance myscript.sh 3 la sortie est

3 {1..3}

au lieu de

3 1
3 2
3 3

Clairement $3 contient la bonne valeur, alors pourquoi for i in {1..$1} se comporte comme si j'avais écrit for i in {1..3} directement?

46
spraff

Vous devez utiliser une boucle for de style C pour y parvenir:

for ((i=1; i<=$1; i++)); do
   echo $i
done

Cela évite les commandes externes et les mauvaises déclarations eval.

67
jordanm

Parce que l'accolade se produit avant l'expansion des variables. http://www.gnu.org/software/bash/manual/bashref.html#Brace-Expansion .

Si vous souhaitez utiliser des accolades, vous pouvez donc quelque chose de sombre comme ceci:

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

Résumé: Bash est vil.

27

Vous pouvez utiliser la commande seq:

for i in `seq 1 $1`

Ou vous pouvez utiliser le style C for...loop:

for((i=1;i<=$1;i++))
15
kev

Voici un moyen d'étendre les variables à l'intérieur des accolades sans eval:

end=3
declare -a 'range=({'"1..$end"'})'

Nous avons maintenant un joli tableau de nombres:

for i in ${range[@]};do echo $i;done
1
2
3
2
Jonathan Cross

Je sais que vous avez mentionné bash dans l'en-tête, mais j'ajouterais que "pour i dans {$ 1 .. $ 2}" fonctionne comme prévu dans zsh. Si votre système a installé zsh, vous pouvez simplement changer votre Shebang en zsh.

L'utilisation de zsh avec l'exemple 'for i in {$ 1 .. $ 2}' a également l'avantage supplémentaire que $ 1 peut être inférieur à 2 $ et cela fonctionne toujours, ce qui nécessiterait beaucoup de détails si vous vouliez ce genre de flexibilité avec une boucle de style C.

1
Joshua