可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I\'m starting to learn about writing scripts for the bash terminal, but I can\'t work out how to get the comparisons to work properly. The script I\'m using is:
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;
The problem I have is that it compares the number from the first digit on, i.e. 9 is bigger than 10000, but 1 is greater than 09
How can I convert the numbers into a type to do a true comparison?
回答1:
In bash, you should do your check in arithmetic context:
if (( a > b )); then
...
fi
For POSIX shells that don\'t support (())
, you can use -lt
and -gt
.
if [ \"$a\" -gt \"$b\" ]; then
...
fi
You can get a full list of comparison operators with help test
.
回答2:
Plain and simple
#!/bin/bash
a=2462620
b=2462620
if [ \"$a\" -eq \"$b\" ];then
echo \"They\'re equal\";
fi
You can check out this cheatsheet if you want more number comparsions in the wonderful world of Bash Scripting.
Shortly, integers can only be compared with:
-eq # equal
-ne # not equal
-lt # less than
-le # less than or equal
-gt # greater than
-ge # greater than or equal
回答3:
There is also one nice thing some people might not know about:
echo $(( a < b ? a : b ))
This code will print the smallest number out of a
and b
回答4:
In Bash I prefer doing this as it addresses itself more as a conditional operation unlike using (( ))
which is more of arithmetic.
[[ N -gt M ]]
Unless I do complex stuffs like
(( (N + 1) > M ))
But everyone just has their own preferences. Sad thing is that some people impose their unofficial standards.
Update:
You actually can also do this:
[[ \'N + 1\' -gt M ]]
Which allows you to add something else which you could do with [[ ]]
besides arithmetic stuffs.
回答5:
This code can also compare floats. It is using awk (it is not pure bash), however this shouldn\'t be a problem, as awk is a standard POSIX command that is most likely shipped by default with your operating system.
$ 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 $?
To make it shorter for use, use this function:
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
回答6:
I solved this by using a small function to convert version strings to plain integer values that can be compared:
function versionToInt() {
local IFS=.
parts=($1)
let val=1000000*parts[0]+1000*parts[1]+parts[2]
echo $val
}
This makes two important assumptions:
- Input is a \"normal SemVer string\"
- Each part is between 0-999
For example
versionToInt 12.34.56 # --> 12034056
versionToInt 1.2.3 # --> 1002003
Example testing whether npm
command meets minimum requirement ...
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
回答7:
If you have floats you can write a function and then use that e.g.
#!/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