2012-03-28 10 views
22

Aquí es myscript.sh

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

Si me quedo myscript.sh 3 la salida es

3 {1..3} 

en lugar de

3 1 
3 2 
3 3 

Claramente $3 contiene el valor correcto, entonces ¿por qué for i in {1..$1} no se comporta como si yo había escrito for i in {1..3} directamente?

+1

Su script de ejemplo funcionará en ambos ksh93 y zsh . –

Respuesta

43

Se debe utilizar un estilo de C para el lazo para lograr esto:

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

Esto evita los comandos externos y desagradables declaraciones de evaluación.

+0

No funciona para mí 'test.sh: línea 1: ((: i <=: error de sintaxis: operando esperado (token de error es" <= ")' – Temak

+0

@Temak ¿Estás usando 'bash'? Es tu shebang' #!/bin/bash' o '#!/bin/sh'? – jordanm

+0

@jordann, el archivo contiene solo estas 3 líneas. Estoy usando GNU bash, versión 4.3.11 (1) -release (x86_64-pc- linux-gnu). Ejecuto el script 'bash test.sh' – Temak

18

Porque la expansión de la abrazadera se produce antes de la expansión de las variables. http://www.gnu.org/software/bash/manual/bashref.html#Brace-Expansion.

Si desea utilizar los frenos, podría por lo que algo sombrío como esto:

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

Resumen: Bash es vil.

+1

Heh, +1 para la respuesta, -0.5 para el vil. –

+1

@glennjackman: Wow, ¿estás diciendo que las innumerables reglas de expansión y escape de Bash no son viles? –

+0

Me siento sucio por decir +1 en una respuesta que implica 'eval'. Re: vile: 'bash' no es vil, pero es un poco como beber alcohol de grano directamente. A algunas personas parece gustarles, pero es difícil no ahogarse al principio y cuanto más lo haces, menos te molesta. – Sorpigal

11

Puede utilizar seq comando:

for i in `seq 1 $1` 

O puede utilizar el estilo C for...loop:

for((i=1;i<=$1;i++)) 
+0

Se prefiere un C-style for loop sobre el comando seq externo. – jordanm

+0

@jordanm Es una buena idea. – kev

+0

muy bueno, con seq puedes cambiar el paso! –

1

Sé que mencionaste bash en el encabezado, pero agregaría que 'para mí en {$ 1 .. $ 2}' funciona según lo previsto en zsh. Si su sistema tiene zsh instalado, puede simplemente cambiar su shebang a zsh.

El uso de zsh con el ejemplo 'for i in {$ 1 .. $ 2}' también tiene el beneficio adicional de que $ 1 puede ser menos de $ 2 y aún funciona, algo que requeriría un poco de confusión si quisiera ese tipo de flexibilidad con un estilo C para bucle.

0

Aquí es una forma de expandir las variables dentro de llaves sin eval:

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

Ahora tenemos un buen conjunto de números:

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