programas - scripts bash ejemplos
¿Cómo puedo agregar números en un script de bash? (10)
Tengo este script de bash y tuve un problema en la línea 16. ¿Cómo puedo tomar el resultado anterior de la línea 15 y agregarlo a la variable en la línea 16?
#!/bin/bash
num=0
metab=0
for ((i=1; i<=2; i++)); do
for j in `ls output-$i-*`; do
echo "$j"
metab=$(cat $j|grep EndBuffer|awk ''{sum+=$2} END { print sum/120}'') (line15)
num= $num + $metab (line16)
done
echo "$num"
done
Debes declarar el metab como un entero y luego usar la evaluación aritmética
declare -i metab num
...
num+=metab
...
Para obtener más información, consulte https://www.gnu.org/software/bash/manual/html_node/Shell-Arithmetic.html#Shell-Arithmetic
En bash,
num=5
x=6
(( num += x ))
echo $num # ==> 11
Tenga en cuenta que bash solo puede manejar la aritmética de enteros, por lo que si su comando awk devuelve una fracción, entonces querrá rediseñar: aquí está su código reescrito un poco para hacer todas las matemáticas en awk.
num=0
for ((i=1; i<=2; i++)); do
for j in output-$i-*; do
echo "$j"
num=$(
awk -v n="$num" ''
/EndBuffer/ {sum += $2}
END {print n + (sum/120)}
'' "$j"
)
done
echo "$num"
done
Hay mil y una formas de hacerlo. Aquí hay uno usando dc
:
dc <<<"$num1 $num2 + p"
Pero si eso es demasiado bash-y para usted (o la portabilidad es importante) podría decir
echo $num1 $num2 + p | dc
Pero tal vez eres una de esas personas que piensan que RPN es icky y raro; no te preocupes bc
está aquí para usted:
bc <<< "$num1 + $num2"
echo $num1 + $num2 | bc
Dicho esto, hay algunas mejoras no relacionadas que podría estar haciendo en su script
#!/bin/bash
num=0
metab=0
for ((i=1; i<=2; i++)); do
for j in output-$i-* ; do # for can glob directly, no need to ls
echo "$j"
# grep can read files, no need to use cat
metab=$(grep EndBuffer "$j" | awk ''{sum+=$2} END { print sum/120}'')
num=$(( $num + $metab ))
done
echo "$num"
done
EDITAR:
Como se describe en BASH FAQ 022 , bash no admite de forma nativa los números de punto flotante. Si necesita sumar números de punto flotante, se requiere el uso de una herramienta externa (como bc
o dc
).
En este caso la solución sería
num=$(dc <<<"$num $metab + p")
Para sumar, acumule números posiblemente de punto flotante en num
.
Otra forma compatible con POSIX
portátil de hacer bash
, que se puede definir como una función en .bashrc
para todos los operadores aritméticos de conveniencia.
addNumbers () {
local IFS=''+''
printf "%s/n" "$(( $* ))"
}
y solo llámalo en la línea de comandos como,
addNumbers 1 2 3 4 5 100
115
La idea es usar el Input-Field-Separator(IFS) , una variable especial en bash
usa para dividir palabras después de la expansión y para dividir líneas en palabras. La función cambia el valor localmente para usar el carácter de división de palabras como el operador suma +
.
Recuerde que el IFS
se cambia localmente y NO tiene efecto en el comportamiento predeterminado del IFS
fuera del alcance de la función. Un extracto de la página de man bash
,
El shell trata cada carácter de IFS como un delimitador y divide los resultados de las otras expansiones en palabras sobre estos caracteres. Si IFS no está configurado, o su valor es exactamente, se omiten los valores predeterminados, las secuencias y el comienzo y el final de las expansiones anteriores, y cualquier secuencia de caracteres IFS que no esté al principio o al final sirve para delimitar palabras.
El "$(( $* ))"
representa la lista de argumentos pasados a ser divididos por +
y luego el valor de la suma se genera usando la función printf
. La función se puede ampliar para agregar también el alcance de otras operaciones aritméticas.
Siempre olvido la sintaxis, por lo que vengo a Google, pero nunca encuentro la que estoy familiarizado con: P. Esto es lo más limpio para mí y más fiel a lo que esperaría en otros idiomas.
i=0
((i++))
echo $i;
También me gusta mucho este método, menos desorden:
count=$[count+1]
Usa la expansión aritmética $(( ))
.
num=$(( $num + $metab ))
Consulte http://tldp.org/LDP/abs/html/arithexp.html para obtener más información.
Para enteros :
Use la expansión aritmética :
$((EXPR))
num=$((num1 + num2)) num=$(($num1 + $num2)) # also works num=$((num1 + 2 + 3)) # ... num=$[num1+num2] # old, deprecated arithmetic expression syntax
Usando la utilidad
expr
externa. Tenga en cuenta que esto solo es necesario para sistemas realmente antiguos.num=`expr $num1 + $num2` # whitespace for expr is important
Para punto flotante :
Bash no admite directamente esto, pero hay un par de herramientas externas que puedes usar:
num=$(awk "BEGIN {print $num1+$num2; exit}")
num=$(python -c "print $num1+$num2")
num=$(perl -e "print $num1+$num2")
num=$(echo $num1 + $num2 | bc) # whitespace for echo is important
También puede utilizar la notación científica (por ejemplo: 2.5e+2
)
Trampas comunes :
Cuando configura una variable, no puede tener espacios en blanco en ninguno de los lados de
=
, de lo contrario, forzará al shell a interpretar la primera palabra como el nombre de la aplicación que se ejecutará (por ejemplo:num=
onum
)num= 1
num =2
bc
yexpr
esperan cada número y operador como un argumento separado, por lo que el espacio en blanco es importante. No pueden procesar argumentos como3+
+4
.num=`expr $num1+ $num2`
#!/bin/bash
read X
read Y
echo "$(($X+$Y))"
#!/bin/bash
num=0
metab=0
for ((i=1; i<=2; i++)); do
for j in `ls output-$i-*`; do
echo "$j"
metab=$(cat $j|grep EndBuffer|awk ''{sum+=$2} END { print sum/120}'') (line15)
let num=num+metab (line 16)
done
echo "$num"
done