2010-03-18 16 views
9

Escribí un archivo .sh para compilar y ejecutar algunos programas para una tarea. Tengo un bucle "for" en el guión, pero no va a funcionar a menos que utilice sólo enteros:¿Los bucles de Shell usan números enteros?

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

El $ i variable es una entrada para el programa de hw3_2_2, y tengo valores no enteros I me gustaría usar ¿Cómo podría ejecutar el código con una lista de números decimales?

Respuesta

9

La forma más fácil es simplemente una lista de ellas:

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

Si la lista es enorme, por lo que no puede tenerlo como una lista literal, considere deshacerse de ellos en un archivo y luego usar algo como

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

los $ (< mi-numbers.txt) parte es una forma eficiente (en Bash) para sustituir el contenido de los nombres de archivo en esa ubicación del script. Gracias a Dennis Williamson por señalar que no es necesario usar el comando externo cat para esto.

+2

uso inútil de 'cat'. En Bash: '$ (

+0

@Dennis: cierto, corregiré. Gracias. – unwind

0

bash no hace números decimales. O utilice algo como bc que pueda, o pase a un lenguaje de programación más completo. Sin embargo, ten cuidado con accuracy problems.

1

Aquí hay otra manera. Puede utilizar un aquí doc para incluir sus datos en el guión:

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

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

mismo modo:

array=(
1.1 
2.12 
3.14159 
4 
5.05 
) 

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

puede usar awk para generar sus decimales, por ejemplo, medidas de 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 puede hacerlo en su totalidad en awk

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

Es una mala práctica usar bucles de coma flotante así porque si sigues sumando 0.1 a 1 nunca llegarás a 10. El contador pasará de algo como 9.9999999999999822 a 10.099999999999982. – Gabe

+0

has probado? Por favor, intente y dígame si llegará a 10. – ghostdog74

+0

Si cambia el '<= 10' al' <10', esperaría que la salida cambiara, ¿verdad? ¿Lo hace? – Gabe

22

Me resulta sorprendente que en cinco años nadie mencionó la utilidad creada solo para generar rangos, pero, una vez más, proviene de BSD alrededor de 2005, y tal vez ni siquiera estaba generalmente disponible en Linux en el momento de la pregunta se hizo.

Pero aquí está:

for i in $(seq 0 0.1 1) 

O, para imprimir todos los números con la misma anchura (anteponiendo o añadiendo ceros), utilice -w. Eso ayuda a evitar que los números se envíen como "enteros", si eso podría causar problemas.

La sintaxis es seq [first [incr]] last, con first defecto a 1, y incr defecto a 1 o -1, dependiendo de si last es mayor que o menor que first. Para otros parámetros, vea seq(1).

+0

¡Esta es definitivamente la respuesta correcta! – rhombidodecahedron

+0

Hola Daniel, ¿hay alguna manera de incrementar este x.x.x en for loop? Por ejemplo, para i en $ (seq 1.0.20 0.0.1 1.0.24). ¿O hay una forma de incrementar esta versión # y agregarla a una lista para poder usarla en for loop? ¡Gracias! – user1164061

0

lo general también uso "ss" como por la segunda respuesta, pero Sólo para dar una respuesta en términos de un bucle de número entero de precisión-robusta y luego bc conversión a un flotador:

#!/bin/bash 

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

Da:

.2 .4 .6 .8 1,0

Cuestiones relacionadas