script - Comparación de punto flotante con variable en bash
expr substr linux (2)
Bash no puede manejar carrozas. Pipe to bc
lugar:
if [ $(echo " $test > $k" | bc) -eq 1 ]
El error que ves es porque el comando de test
(es decir, el [
) necesita espacios antes y después
Es incluso mejor usar (( ... ))
ya que comparas números como este:
if (( $(bc <<< "$test > $k") ))
La parte del ciclo debería verse así:
if (( $(bc <<< "$test <= 1") ))
then
echo "output"
elif (( $(bc <<< "$test > $k") ))
then
echo "output$k"
fi
Las expresiones relacionales evalúan a 0, si la relación es falsa, y 1 si la relación es verdadera [ source ]. Sin embargo, tenga en cuenta que es un comportamiento de GNU bc
y no es un compilador de POSIX
.
Esta pregunta ya tiene una respuesta aquí:
- Bash: Expresión Integer esperada [duplicado] 2 respuestas
Quiero comparar una variable de coma flotante con un entero. Sé que esto no es lo mejor que puedo hacer con bash, pero todo el guión ya está escrito en bash. $ number puede ser cualquier número entero. Si está por debajo o igual a 50, quiero la salida 1, para todos los demás quiero una salida con la otra variable k. Esto es lo que tengo hasta ahora:
number=43
test=$(echo "scale=2; $number/50" | bc -l)
echo "$test"
for k in {1..5}
do
if ["$test" -le 1]
then echo "output"
elif ["$test" -gt $k]
then echo "output$k"
fi
done
Si intento con test = 0.43, el primer ciclo ni siquiera funciona. Creo que tiene que ver con un entero y una comparación de coma flotante, pero no puede hacer que funcione.
¿Algo que me falta?
PD: este [0.43: command not found
es lo que produce el terminal.
Es una vieja pregunta, pero creo que tiene una respuesta adicional.
Mientras que la conexión a una calculadora de mayor precisión (bc o dc) funciona, es a costa de una bifurcación y un proceso adicional, ya que esas calculadoras no están incorporadas en bash. Una cosa que está incorporada, sin embargo, es printf
. Entonces, si puede tratar con sus números dentro de un número particular de decimales, puede "falsificar" comparaciones de coma flotante, con una función como esta:
#!/usr/bin/env bash
function [[[ () {
local LANG=C lhs rhs
printf -v lhs ''%07.3f'' "$1"; lhs=${lhs/./}
printf -v rhs ''%07.3f'' "$3"; rhs=${rhs/./}
case "$2" in
-lt) return $(( ! ( 10#$lhs < 10#$rhs ) )) ;;
-le) return $(( ! ( 10#$lhs <= 10#$rhs ) )) ;;
-eq) return $(( ! ( 10#$lhs == 10#$rhs ) )) ;;
-ge) return $(( ! ( 10#$lhs >= 10#$rhs ) )) ;;
-gt) return $(( ! ( 10#$lhs > 10#$rhs ) )) ;;
esac
}
number=${1:-43}
test=$(dc -e "2k $number 50 / p")
echo "$test"
for k in {1..5}; do
if [[[ "$test" -le 1 ]]]; then
echo "output"
elif [[[ "$test" -gt "$k" ]]]; then
echo "output $k"
fi
done
Algunas cosas para considerar aquí.
- He llamado a la función
[[[
que sea linda. Puedes ponerle el nombre que quieras.ntest
omynumericcomparison
o incluso[[[
. -
printf
es una función interna dentro de bash, por lo tanto, a pesar de que está en su camino, no cuesta una bifurcación. - Tal como está, la función admite números hasta 999.999. Si necesita números más altos (o más precisión), ajuste los formatos de
printf
. - El
10#
al comienzo de cada variable dentro de la declaración delcase
es forzar la comparación en la base 10, ya que un número sin relleno podría interpretarse como octal.
Ver también: http://mywiki.wooledge.org/BashFAQ/022