2010-03-18 12 views
9

Ho scritto un file .sh per compilare ed eseguire alcuni programmi per un compito a casa. Ho un ciclo "for" nella sceneggiatura, ma non funzionerà a meno che io uso solo numeri interi:I cicli di shell utilizzano valori non interi?

#!/bin/bash 
for ((i=10; i<=100000; i+=100)) 
do 
    ./hw3_2_2 $i 
done 

Il $ i variabile è un input per il programma di hw3_2_2, e ho valori non interi I 'mi piacerebbe usare. Come posso eseguire il ciclo di esecuzione del codice con un elenco di numeri decimali?

risposta

9

Il modo più semplice è quello di elencare solo loro:

for a in 1.2 3.4 3.11 402.12 4.2 2342.40 
do 
    ./hw3_2_2 $a 
done 

Se la lista è enorme, quindi non si può avere come una lista letterale, considerare il dumping in un file e poi usando qualcosa come

for a in $(< my-numbers.txt) 
do 
    ./hw3_2_2 $a 
done 

i $ (< my-numbers.txt) parte è un modo efficace (in Bash) per sostituire il contenuto dei nomi dei file in quella posizione dello script. Grazie a Dennis Williamson per aver sottolineato che non è necessario utilizzare il comando esterno cat per questo.

+2

uso inutile di 'cat'. In Bash: '$ (

+0

@Dennis: true, correggerò. Grazie. – unwind

0

bash non fa numeri decimali. O utilizzare qualcosa come bc che può, o passare a un linguaggio di programmazione più completo. Attenzione però a accuracy problems.

1

Ecco un altro modo. È possibile utilizzare un qui doc per includere i dati nello script:

read -d '' data <<EOF 
1.1 
2.12 
3.14159 
4 
5.05 
EOF 

for i in $data 
do 
    ./hw3_2_2 $i 
done 

Allo stesso modo:

array=(
1.1 
2.12 
3.14159 
4 
5.05 
) 

for i in ${array[@]} 
do 
    ./hw3_2_2 $i 
done 
8

è possibile utilizzare awk per generare i decimali es passi di 0.1

num=$(awk 'BEGIN{for(i=1;i<=10;i+=0.1)print i}') 
for n in $num 
do 
    ./hw3_2_2 $n 
done 

o puoi farlo interamente in awk

awk 'BEGIN{cmd="hw3_2_2";for(i=1;i<=10;i+=0.1){c=cmd" "i;system(cmd) } }' 
+1

È una cattiva pratica usare il punto mobile in loop come quello perché se continui ad aggiungere 0.1 a 1 non arrivi mai a 10. Il contatore andrà da qualcosa come 9.9999999999999822 a 10.099999999999982. – Gabe

+0

hai provato? pls prova e poi dimmi se arriverà a 10. – ghostdog74

+0

Se cambi il '<= 10' a' <10' ti aspetteresti che l'output cambi, giusto? Lo fa? – Gabe

22

Trovo sorprendente che in cinque anni nessuno abbia mai menzionato l'utilità creata solo per generare gamme, ma, ancora una volta, viene da BSD verso il 2005, e forse non era nemmeno generalmente disponibile su Linux al momento della domanda era fatto.

Ma qui è:

for i in $(seq 0 0.1 1) 

Oppure, per stampare tutti i numeri con la stessa larghezza (anteponendo o aggiungendo zeri), utilizzare -w. Ciò aiuta a evitare che i numeri vengano inviati come "interi", se ciò causerebbe problemi.

La sintassi è seq [first [incr]] last, con first inadempiente a 1, e incr inadempiente a 1 o -1, a seconda che last è maggiore o minore di first. Per altri parametri, vedere seq(1).

+0

Questa è sicuramente la risposta giusta! – rhombidodecahedron

+0

Ciao Daniel, c'è un modo per incrementare questo ciclo x.x.x in per? Ad esempio per i in $ (seq 1.0.20 0.0.1 1.0.24). O c'è un modo per incrementare questa versione # e aggiungerla a un elenco in modo che io possa usarlo in ciclo for? Grazie! – user1164061

0

solito uso anche "seq" come per la seconda risposta, ma solo per dare una risposta in termini di un ciclo intero di precisione robusti e quindi bc conversione ad un galleggiante:

#!/bin/bash 

for i in {2..10..2} ; do 
    x=`echo "scale=2 ; ${i}/10" | bc` 
    echo $x 
done 

dà:

.2 .4 .6 .8 1,0

Problemi correlati