bash - programas - script linux ejemplos
Comparando nĂºmeros en Bash (7)
Estoy empezando a aprender cómo escribir guiones para el terminal bash, pero no puedo averiguar cómo hacer que las comparaciones funcionen correctamente. El script que estoy usando es:
echo "enter two numbers";
read a b;
echo "a=$a";
echo "b=$b";
if [ $a /> $b ];
then
echo "a is greater than b";
else
echo "b is greater than a";
fi;
El problema que tengo es que compara el número a partir del primer dígito, es decir, 9 es mayor que 10000, pero 1 es mayor que 09
¿Cómo puedo convertir los números en un tipo para hacer una comparación verdadera?
En Bash, prefiero hacer esto, ya que se trata más como una operación condicional, a diferencia de usar (( ))
que es más de aritmética.
[[ N -gt M ]]
A menos que haga cosas complejas como
(( (N + 1) > M ))
Pero cada uno tiene sus propias preferencias. Lo triste es que algunas personas imponen sus estándares no oficiales.
Actualizar:
En realidad, también puede hacer esto:
[[ ''N + 1'' -gt M ]]
Lo que le permite agregar algo más que podría hacer con [[ ]]
además de elementos aritméticos.
En bash, debes hacer tu comprobación en el contexto aritmético :
if (( a > b )); then
...
fi
Para shells POSIX que no admiten (())
, puede usar -lt
y -gt
.
if [ "$a" -gt "$b" ]; then
...
fi
Puede obtener una lista completa de operadores de comparación con la help test
.
Este código también puede comparar flotadores. Está utilizando awk (no es bash puro), sin embargo, esto no debería ser un problema, ya que awk es un comando POSIX estándar que probablemente se envía de forma predeterminada con su sistema operativo.
$ awk ''BEGIN {return_code=(-1.2345 == -1.2345) ? 0 : 1; exit} END {exit return_code}''
$ echo $?
0
$ awk ''BEGIN {return_code=(-1.2345 >= -1.2345) ? 0 : 1; exit} END {exit return_code}''
$ echo $?
0
$ awk ''BEGIN {return_code=(-1.2345 < -1.2345) ? 0 : 1; exit} END {exit return_code}''
$ echo $?
1
$ awk ''BEGIN {return_code=(-1.2345 < 2) ? 0 : 1; exit} END {exit return_code}''
$ echo $?
0
$ awk ''BEGIN {return_code=(-1.2345 > 2) ? 0 : 1; exit} END {exit return_code}''
$ echo $?
Para que sea más corto de usar, use esta función:
compare_nums()
{
# Function to compare two numbers (float or integers) by using awk.
# The function will not print anything, but it will return 0 (if the comparison is true) or 1
# (if the comparison is false) exit codes, so it can be used directly in shell one liners.
#############
### Usage ###
### Note that you have to enclose the comparison operator in quotes.
#############
# compare_nums 1 ">" 2 # returns false
# compare_nums 1.23 "<=" 2 # returns true
# compare_nums -1.238 "<=" -2 # returns false
#############################################
num1=$1
op=$2
num2=$3
E_BADARGS=65
# Make sure that the provided numbers are actually numbers.
if ! [[ $num1 =~ ^-?[0-9]+([.][0-9]+)?$ ]]; then >&2 echo "$num1 is not a number"; return $E_BADARGS; fi
if ! [[ $num2 =~ ^-?[0-9]+([.][0-9]+)?$ ]]; then >&2 echo "$num2 is not a number"; return $E_BADARGS; fi
# If you want to print the exit code as well (instead of only returning it), uncomment
# the awk line below and comment the uncommented one which is two lines below.
#awk ''BEGIN {print return_code=(''$num1'' ''$op'' ''$num2'') ? 0 : 1; exit} END {exit return_code}''
awk ''BEGIN {return_code=(''$num1'' ''$op'' ''$num2'') ? 0 : 1; exit} END {exit return_code}''
return_code=$?
return $return_code
}
$ compare_nums -1.2345 ">=" -1.2345 && echo true || echo false
true
$ compare_nums -1.2345 ">=" 23 && echo true || echo false
false
Resolví esto usando una pequeña función para convertir cadenas de versión a valores enteros simples que se pueden comparar:
function versionToInt() {
local IFS=.
parts=($1)
let val=1000000*parts[0]+1000*parts[1]+parts[2]
echo $val
}
Esto hace dos suposiciones importantes:
- La entrada es una " cadena normal de SemVer "
- Cada parte está entre 0-999
Por ejemplo
versionToInt 12.34.56 # --> 12034056
versionToInt 1.2.3 # --> 1002003
Ejemplo de prueba para ver si el comando npm
cumple con el requisito mínimo ...
NPM_ACTUAL=$(versionToInt $(npm --version)) # Capture npm version
NPM_REQUIRED=$(versionToInt 4.3.0) # Desired version
if [ $NPM_ACTUAL /< $NPM_REQUIRED ]; then
echo "Please update to npm@latest"
exit 1
fi
Sencillo y sencillo
#!/bin/bash
a=2462620
b=2462620
if [ "$a" -eq "$b" ];then
echo "They''re equal";
fi
Puede consultar esta hoja de trucos si desea más comparaciones de números en el maravilloso mundo de Bash Scripting.
En breve, los enteros solo se pueden comparar con:
-eq # equal
-ne # not equal
-lt # less than
-le # less than or equal
-gt # greater than
-ge # greater than or equal
Si tiene flotadores, puede escribir una función y luego usarla, por ejemplo,
#!/bin/bash
function float_gt() {
perl -e "{if($1>$2){print 1} else {print 0}}"
}
x=3.14
y=5.20
if [ $(float_gt $x $y) == 1 ] ; then
echo "do stuff with x"
else
echo "do stuff with y"
fi
También hay una cosa buena que algunas personas pueden no saber:
echo $(( a < b ? a : b ))
Este código imprimirá el número más pequeño de a
y b