Comparación de punto flotante con variable en bash

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 bash 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.

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 [ fuente ]. Sin embargo, tenga en cuenta que es un comportamiento de GNU bc y no es un comstackdor de POSIX .

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 o mynumericcomparison 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 statement del case 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