2012-06-28 27 views
18

Estoy tratando de comparar dos valores decimales pero recibo errores. Solía ​​¿Cómo comparar dos números decimales en bash/awk?

if [ "$(echo $result1 '>' $result2 | bc -l)" -eq 1 ];then 

según lo sugerido por el otro hilo de desbordamiento de pila.

Recibo errores.

¿Cuál es la forma correcta de hacerlo?

+0

¿Cuáles son los errores? mal escrito un nombre de variable. – ormaaj

+0

en realidad los errores se deben a otros problemas. Esto funciona bien –

+0

¿Qué quiere decir con 'valores decimales'? ¿Te refieres a enteros en la base 10, o te refieres a cadenas que representan valores reales no enteros? –

Respuesta

29

Puede hacerlo utilizando contexto numérico de Bash:

if (($(echo "$result1 > $result2" | bc -l))); then 

bc dará salida a 0 ó 1 y el (()) va a interpretarlos como falsa o verdadera, respectivamente.

Lo mismo usando AWK:

if (($(echo "$result1 $result2" | awk '{print ($1 > $2)}'))); then 
+10

+1 para la solución awk, pero: 'si echo $ resultado1 $ resultado2 | awk '{exit! ($ 1> $ 2)}'; entonces ... ' –

+0

Me gusta retractarme de mi voto porque la respuesta de Dennis es correcta con puntos decimales. Para la aritmética de coma flotante ampliada utilizando bash, consulte mi respuesta a continuación. – Samir

+0

@Samir: si aún no lo has hecho, puedes volver a hacer clic en la flecha hacia abajo para invertir el downvote. –

-1

También puede echo una declaración if...else a bc.

- echo $result1 '>' $result2 
+ echo "if (${result1} > ${result2}) 1 else 0" 

(
#export IFS=2 # example why quoting is important 
result1="2.3" 
result2="1.7" 
if [ "$(echo $result1 '>' $result2 | bc -l)" -eq 1 ]; then echo yes; else echo no;fi 
if [ "$(echo "if (${result1} > ${result2}) 1 else 0" | bc -l)" -eq 1 ];then echo yes; else echo no; fi 
if echo $result1 $result2 | awk '{exit !($1 > $2)}'; then echo yes; else echo no; fi 
) 
8
if awk 'BEGIN{exit ARGV[1]>ARGV[2]}' "$z" "$y" 
then 
    echo z not greater than y 
else 
    echo z greater than y 
fi 
-3

¿Por qué utilizar bc?

for i in $(seq -3 0.5 4) ; do echo $i ; if [[ (("$i" < 2)) ]] ; then echo "... is < 2";fi; done 

El único problema: la comparación "<" no funciona con números negativos: se toman como su valor absoluto.

+0

'<' inside '[[...]]' es para la comparación de cadenas (entonces '20' es menor que' 3', y '0.2' es menor que' 1e-50'). Los '(' son redundantes, puede agregar tantos como desee, solo son para agrupar. –

-2

¿No puede bash la conversión de tipo de fuerza? Por ejemplo:

($result1 + 0) < ($result2 + 0) 
+0

Sin bash no puede forzar la conversión de tipos, como perl, etc ... –

0

El seguimiento de la respuesta de Dennis:

pesar de que su respuesta es correcta para los puntos decimales, golpe del lanza (standard_in) 1: error de sintaxis con aritmética de punto flotante.

result1=12 
result2=1.27554e-05 


if (($(echo "$result1 > $result2" | bc -l))); then 
    echo "r1 > r2" 
else 
    echo "r1 < r2" 
fi 

Esto devuelve una salida incorrecta con una advertencia aunque con un código de salida de 0.

(standard_in) 1: error de sintaxis
r1 r2 <

Si bien no hay solución clara a esto (discusión thread 1 y thread 2), utilicé la siguiente solución parcial redondeando los resultados de coma flotante usando awk seguido por el uso de bc comando como en la respuesta de Dennis y this thread

Redondear a una posición decimal deseada: Siguiendo recibirá espacio recursivo de directorios en TB con redondeo en el segundo decimal.

result2=$(du -s "/home/foo/videos" | tail -n1 | awk '{$1=$1/(1024^3); printf "%.2f", $1;}') 

continuación, puede utilizar la aritmética fiesta que el anterior o el uso de [[ ]] recinto como en following thread.

if (($(echo "$result1 > $result2" | bc -l))); then 
    echo "r1 > r2" 
else 
    echo "r1 < r2" 
fi 

o el uso de -eq operador donde bc salida de 1 es cierto y 0 es falsa

if [[ $(bc <<< "$result1 < $result2") -eq 1 ]]; then 
    echo "r1 < r2" 
else 
    echo "r1 > r2" 
fi 
0
if [[ `echo "$result1 $result2" | awk '{print ($1 > $2)}'` == 1 ]]; then 
    echo "$result1 is greater than $result2" 
fi