En bash, ¿es posible usar una variable entera en el control de bucle de un bucle for?


65

Tengo el siguiente script bash:

#!/bin/bash

upperlim=10

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

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

El primer forbucle ( sin la variable upperlimen el control del bucle) funciona bien, pero el segundo forbucle ( con la variable upperlimen el control del bucle) no. ¿Hay alguna manera de que pueda modificar el segundo forbucle para que funcione? Gracias por tu tiempo.


44
hm, incluso for i in {0..$((upperlim))}; do echo $i; doneno funciona
Bonsi Scott

y +1 porque encuentro ese comportamiento interesante
Bonsi Scott


Un enlace externo que responde a esto: cyberciti.biz/faq/…
kon psych

Respuestas:


62

La razón de esto es el orden en que ocurren las cosas en bash. La expansión de llaves se produce antes de que se expandan las variables. Para lograr su objetivo, debe usar el estilo C para el bucle:

upperlim=10

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

1
Y trabaja para zshasí (pero no para csh, tcsh).
Matemáticas el

29

Para completar esto en su estilo usando nada más que elementos integrados, deberá usar eval:

d=12

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

Pero con seq:

lowerlimit=0
upperlimit=12

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

Personalmente, encuentro que el uso de seqes más legible.


Para "incorporados"? seqes un comando externo y no está disponible en todas partes bash es.
jordanm

99
@jordanm: para usar todos los builtins con bash. Luego dije "pero con seq", reconociendo que no es una función integrada.
Jodie C

El hecho de que la expansión del aparato ortopédico esté incorporado no es el problema aquí. reades un incorporado, por ejemplo, pero no hay razón para evalello.
jordanm

1
Las incorporaciones no son problemáticas en absoluto. Quería proporcionar una solución completa para el autor de la pregunta. Si quieres seguir discutiendo sobre esto, llévalo al chat; los comentarios no son buenos para este tipo de cosas
Jodie C

8

La manera POSIX

Si le importa la portabilidad, use el ejemplo del estándar POSIX :

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

Salida:

2
3
4
5

Cosas que no son POSIX:


1

Su enfoque no funcionará ya que en bash brace-expansion ocurre antes de la expansión de parámetros. Necesita expandir la variable antes.

Puede trabajar con eval :

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

Con el bucle While :

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

También puedes hacerlo con el comando seq :

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

Si desea ejecutar con for i in {0..$upperlim}, necesitará usar kornshell. p.ej:

#!/bin/ksh
upperlim=10

for i in {0..$upperlim}
do
        echo $i
done
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.