2011-02-10 20 views
6

Tengo un problema con las secuencias integradas (es decir: no usa seq) en Bash cuando el número de secuencia es una variable. Por ejemplo, esto funciona e imprimir me 1 2 3:Expansión de secuencias y variable en bash

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

pero esto:

bash3.2 $ a = 3; para i in {1 .. $ a}; hacer $ eco i; hecho

fallar y me imprimir {1..3} solamente

esto funciona con ZSH y sé que tengo una alternativa a hacer una cosa mostrador, pero se pregunta si esto es un error o un aparato ortopédico ¡función de expansión!

+1

posible duplicado de [argumentos que se pasan en bucle for de escritura del golpe] (http://stackoverflow.com/ preguntas/4764383/arguments-passed-into-for-loop-in-bash-script) –

Respuesta

4

En Bash, expansión de llaves se realiza antes de la expansión variable. Ver Shell Expansions para la orden.

$ a=7; echo {1..3} {4..$a} 
1 2 3 {4..7} 

Si desea utilizar una variable, utilice C-estilo for bucles como en la respuesta de Shawn.

3
$ num=3 
$ for i in $(eval echo {1..$num});do echo $i;done 
1 
2 
3 
+0

parece una especie de truco para mí ... pero gracias .. –

+0

Menos eficiente que un ciclo estilo C (debido al uso de una subshell) y conlleva un riesgo de seguridad: no use 'eval' a menos que controle completamente o haya validado el valor de las variables utilizadas en la cadena que se pasa a' eval'. De lo contrario, se pueden ejecutar comandos arbitrarios. Por ejemplo, el siguiente valor '$ num' cuidadosamente elaborado enumerará los archivos en la carpeta de inicio del usuario actual: ' num = '}; ls ~; {'; para i en $ (eval echo {1 .. $ num}); do echo $ i; done' – mklement0

4

Una alternativa sería el uso de la construcción de doble paréntesis que permite bucles C-style:

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

Hola, no estoy interesado en usar comandos externos sino bash interno incorporado. –

+0

él no quiere usar 'seq' – kurumi

+0

Lo siento, lo perdí. Respuesta actualizada –

1

Otra opción es utilizar comandos siguientes:

a=3; for i in $(seq 1 $a);do echo $i;done 
+0

No es eficiente debido al uso de una utilidad externa, pero es simple y funciona. – mklement0

-1

probar esto:

$ start=3 
$ end=5 
$ echo {$(echo $start)..$(echo $end)} 
+1

que imprime el siguiente _literal_: '{3..5}', que claramente no es la intención. Si sigue el enlace en la respuesta aceptada, verá que la expansión de llaves ('{...}') ocurre antes de la sustitución del comando ('$ (...)'), por lo que su enfoque no puede funcionar (en _Bash_, como está etiquetado; funcionaría en Ksh y Zsh, pero de todos modos puede usar las variables _directly_ en las expansiones de corchetes, así que simplemente usaría 'start = 3 end = 5; echo {$ start .. $ end}') . – mklement0

+0

disculpa, cometí un error, echo {$ (echo $ start) .. $ (echo $ end)} no funciona, pero {$ start, $ end} muestra "3 5". –

+0

Sí, lo hace, pero esa es la forma _list_ de expansión de llaves (',' -elementos separados), mientras que lo que el OP está buscando es la forma _secuencia_ (rango) ('..'). En términos concretos: no es '3 5' que es la salida deseada, sino' 3 4 5'. – mklement0

0

también necesitaba hacer somenthing como:

n = un número; {1} .. $ n..increment

así que utiliza esta solución:

n=100 
i=1 
while [ $i -lt $n ] 
do 
echo $i 
i=$(($i+1)) 
done 
Cuestiones relacionadas