Comparación de números decimales en bash

Comparación de números decimales en bash

Mi búsqueda esta mañana fue sobre cómo podría comparar dos números decimales en bash, y llegué a esta respuesta:Cómo comparar con un número de coma flotante en un script de shell. Éste, sin embargo, no incluyeesta respuesta aquí:

$ [[ ((3.56 < 2.90)) ]]; echo $?
1
$ [[ ((3.56 < 4.90)) ]]; echo $?
0

Teniendo en cuenta que la respuesta ha sido rechazada y parece una especie de bashismo inusual, ¿es confiable esta evaluación aritmética por su precisión?

Respuesta1

bashNo entiende los números de punto flotante. Página del manual
de cotizaciones bash, secciónEVALUACIÓN ARITMÉTICA:

La evaluación se realiza en números enteros de ancho fijo […].

Entonces ((3 < 4))o ((3 < 2))son en realidad expresiones aritméticas correctas. Puedes escribir lo siguiente:

$ echo "$((3 < 4)) -- $((3 < 2))"

producción:1 -- 0

Pero $ echo $((3.3 < 3.6))devolverá un mensaje de error de sintaxis. En su ejemplo, en realidad está comparando cadenas. De ahí algún ejemplo:

$ [[ ((3.56 < 04.90)) ]]; echo $?

producción:1

Respuesta2

El interior [[...]] <es para comparar cadenas.

Entonces [[ 3.56 < 2.90 ]]or [[ (3.56 < 2.90) ]]or [[ ((3.56 < 2.90)) ]]or [[ (((3.56 < 2.90))) ]]... es simplemente comparar léxicamente la 3.56cadena con la 2.90cadena (y léxicamente, 3es mayor que, 10por ejemplo).

Para comparación de números enteros, es [[ 3 -lt 2 ]]o (( 3 < 2 )). Si desea una comparación de punto flotante, necesita o ksh93una utilidad externa como o ; No puedo hacerlo.zshyashawkperlbash

Por ejemplo, podrías definir una función como:

compare() (IFS=" "
  exec awk "BEGIN{if (!($*)) exit(1)}"
)

Que podrías usar, por ejemplo, como:

if compare '1.5*10 < 1e3'; then
  echo less
fi

O incluso para eso importa:

if compare '"bar" < "foo"'...

para hacer comparaciones de cadenas.

No pase datos proporcionados externamente sin control a esa comparefunción, ya que constituiría una vulnerabilidad de inyección de comandos (los datos se interpretan como awkcódigo, awkpueden ejecutar comandos con él, system()por ejemplo).

información relacionada