2013-06-19 2 views
10

Come si usa una variabile in un ciclo per loop? Se mi basta usare uno standard per ciclo, si fa quello che mi aspettoCome utilizzare le variabili in una bash per il ciclo

for i in {0..3} 
do 
    echo "do some stuff $i" 
done 

Questo funziona bene. Passa attraverso 4 volte, da 0 a 3 incluso, stampando il mio messaggio e mettendo il conteggio alla fine.

do some stuff 0 
do some stuff 1 
do some stuff 2 
do some stuff 3 

Quando provo la stessa cosa con il seguente ciclo for, sembra uguale a una stringa, che non è quello che voglio.

length=3 
for i in {0..$length} 
do 
    echo "do something right $i" 
done 

uscita:

do something right {0..3} 

ho provato

for i in {0.."$length"} and for i in {0..${length}} (both output was {0..3}) 

e

for i in {0..'$length'} (output was {0..$length}) 

ed entrambi non fanno quello che mi serve. Spero che qualcuno possa aiutarmi. Grazie in anticipo per l'aiuto di qualsiasi esperto di bash con i loop.

risposta

12

Un modo è usare eval:

for i in $(eval echo {0..$length}) 
do 
     echo "do something right $i" 
done 

Nota cosa succede quando si imposta length=;ls o length=; rm * (non cercare quest'ultima però).

sicurezza, utilizzando seq:

for i in $(seq 0 $length) 
do 
     echo "do something right $i" 
done 

oppure è possibile utilizzare lo stile di c per il ciclo, che è anche sicuro:

for ((i = 0; i <= $length; i++)) 
do 
     echo "do something right $i" 
done 
+3

+1 non è un fan di 'eval' ma, come il modo in cui si danno varie opzioni in questa risposta. –

+1

anello C-stile è ovviamente l'opzione migliore. –

4

In bash, espansione delle parentesi graffe è il primo passo tentato così, a quel punto, $length non sarà stato sostituito.

La pagina del manuale per gli stati bash chiaramente:

Un'espressione sequenza assume la forma {x..y [.. incr]}, dove x ed y sono sia interi o singoli caratteri ...

ci sono una serie di possibilità, come l'utilizzo di:

pax> for i in $(seq 0 $length) ; do echo $i ; done 
0 
1 
2 
3 

che comunque potrebbe dare una grande linea di comando se length è enorme.

Un'altra alternativa è quella di utilizzare il C-like sintassi:

pax> for ((i = 0; i <= $length; i++)) ; do echo $i; done 
0 
1 
2 
3 
3

subtitutions Brace vengono eseguite prima di ogni altro, quindi è necessario utilizzare eval o un terzo strumento come seq.

Esempio per eval:

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

Questa informazione può effettivamente essere trovato in man bash:

Un'espressione sequenza assume la forma {x..y [.. incr]}, dove x ed y sono o interi o singoli caratteri e aum, un incremento opzionale, è un numero intero. [...]

L'espansione delle graffe viene eseguita prima di qualsiasi altra espansione, e caratteri speciali ad altre espansioni sono conservati nel risultato. È strettamente testuale. Bash non applica alcuna interpretazione sintattica al contesto dell'espansione o il testo tra le parentesi.