Ik krijg geen numerieke vergelijkingen die werken:
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;
Het probleem is dat het het nummer van het eerste cijfer op, d.w.z. 9 vergelijkt is groter dan 10, maar 1 is groter dan 09.
Hoe kan ik de nummers in een type converteren om een echte vergelijking te doen?
Antwoord 1, Autoriteit 100%
In Bash, moet u uw cheque in een rekenkundige context :
if (( a > b )); then
...
fi
Voor POSIX-shells die niet ondersteunen (())
, kunt u -lt
en -gt
gebruiken.
if [ "$a" -gt "$b" ]; then
...
fi
U kunt een volledige lijst met vergelijkingsoperators ontvangen met help test
of man test
.
Antwoord 2, Autoriteit 21%
Zoals dit:
#!/bin/bash
a=2462620
b=2462620
if [ "$a" -eq "$b" ]; then
echo "They're equal";
fi
Integers kunnen worden vergeleken met deze operators:
-eq # Equal
-ne # Not equal
-lt # Less than
-le # Less than or equal
-gt # Greater than
-ge # Greater than or equal
Zie deze valsgezel .
Antwoord 3, Autoriteit 5%
Er is ook een leuk ding dat sommige mensen misschien niet weten:
echo $(( a < b ? a : b ))
Deze code drukt het kleinste getal af van a
en b
Antwoord 4, autoriteit 3%
In Bash doe ik dit liever omdat het zichzelf meer als een voorwaardelijke bewerking aanpakt, in tegenstelling tot het gebruik van (( ))
, wat meer rekenkundig is.
[[ n -gt m ]]
Tenzij ik complexe dingen doe, zoals
(( (n + 1) > m ))
Maar iedereen heeft gewoon zijn eigen voorkeuren. Het trieste is dat sommige mensen hun onofficiële normen opleggen.
U kunt dit ook doen:
[[ 'n + 1' -gt m ]]
Hiermee kun je iets anders toevoegen wat je zou kunnen doen met [[ ]]
naast rekenkundige dingen.
Antwoord 5
Deze code kan ook floats vergelijken. Het gebruikt AWK (het is geen pure Bash). Dit zou echter geen probleem moeten zijn, aangezien AWK een standaard POSIX-commando is dat waarschijnlijk standaard bij uw besturingssysteem wordt geleverd.
$ 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 $?
Gebruik deze functie om het korter te maken voor gebruik:
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
Antwoord 6
De dingen tussen haakjes (bijv. [[ $a -gt $b ]]
of (( $a > $b ))
) is niet genoeg als je wilt ook float-nummers gebruiken; het zou een syntaxisfout melden. Als u float-getallen of float-getal met geheel getal wilt vergelijken, kunt u (( $(bc <<< "...") ))
gebruiken.
Bijvoorbeeld
a=2.00
b=1
if (( $(bc <<<"$a > $b") )); then
echo "a is greater than b"
else
echo "a is not greater than b"
fi
U kunt meer dan één vergelijking opnemen in het if-statement. Bijvoorbeeld,
a=2.
b=1
c=1.0000
if (( $(bc <<<"$b == $c && $b < $a") )); then
echo "b is equal to c but less than a"
else
echo "b is either not equal to c and/or not less than a"
fi
Dat is handig als u wilt controleren of een numerieke variabele (integer of niet) binnen een numeriek bereik valt.
Antwoord 7
Als je floats hebt, kun je een functie schrijven en die dan gebruiken. Bijvoorbeeld,
#!/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
Antwoord 8
Ik heb dit opgelost door een kleine functie te gebruiken om versiereeksen te converteren naar gewone integer-waarden die kunnen worden vergeleken:
function versionToInt() {
local IFS=.
parts=($1)
let val=1000000*parts[0]+1000*parts[1]+parts[2]
echo $val
}
Dit maakt twee belangrijke aannames:
- De invoer is een “normale SemVer-tekenreeks“
- Elk deel is tussen 0-999
Bijvoorbeeld
versionToInt 12.34.56 # --> 12034056
versionToInt 1.2.3 # --> 1002003
Voorbeeld van testen of het commando npm
voldoet aan de minimumvereiste…
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 [email protected]"
exit 1
fi