web-dev-qa-db-fra.com

En bash, est-il possible d'utiliser une variable entière dans le contrôle de boucle d'une boucle for?

J'ai le script bash suivant:

#!/bin/bash

upperlim=10

for i in {0..10}
do
echo $i
done

for i in {0..$upperlim}
do
echo $i
done

La première boucle for (sans la variable upperlim dans le contrôle de boucle) fonctionne correctement, mais la deuxième boucle for (avec la variable upperlim dans le contrôle de boucle) ne le fait pas. Existe-t-il un moyen de modifier la deuxième boucle for pour qu'elle fonctionne? Merci pour votre temps.

70
Andrew

La raison en est l'ordre dans lequel les choses se produisent dans bash. L'expansion de l'accolade se produit avant les variables sont développées. Pour atteindre votre objectif, vous devez utiliser le style C pour la boucle:

upperlim=10

for ((i=0; i<=upperlim; i++)); do
   echo "$i"
done
67
jordanm

Pour terminer cela dans votre style en utilisant uniquement des éléments intégrés, vous devez utiliser eval:

d=12

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

Mais avec seq:

lowerlimit=0
upperlimit=12

for i in $(seq $lowerlimit $upperlimit)
do
echo $i
done

Personnellement, je trouve que l'utilisation de seq est plus lisible.

31
Jodie C

La manière POSIX

Si vous vous souciez de la portabilité, utilisez le exemple du standard POSIX :

i=2
END=5
while [ $i -le $END ]; do
    echo $i
    i=$(($i+1))
done

Production:

2
3
4
5

Les choses qui sont pas POSIX:

Votre approche ne fonctionnera pas car dans bash l'accolade-expansion se produit avant l'expansion des paramètres. Vous devez développer la variable avant.

Vous pouvez contourner avec eval :

upperlim=10
eval '
        for i in {0..'"$upperlim"'}
        do
                echo $i
        done
'

Avec Boucle While :

upperlim=10
#with while
start=0
while [[ $start -le $upperlim ]]
do
    echo "$start"
    ((start = start + 1))
done

Vous pouvez aussi le faire avec commande seq :

upperlim=10
#seq
for i in $(seq "$upperlim"); do
  echo "$i"
done

Si vous souhaitez exécuter avec for i in {0..$upperlim} vous devrez utiliser kornshell. par exemple:

#!/bin/ksh
upperlim=10

for i in {0..$upperlim}
do
        echo $i
done
1
Kheshav Sewnundun