Let's say I have a coordinate (x,y), I want to make two categories: good or bad.
I have no idea how to put it into words or keywords, so I created an example of what I want.
I have created a bash script like this:
x=3.5 #(example)
y=-2.5 #(example)
if [ $x -ge 0.1 -a $x -le 5.5 ] && [ $y -ge -5.9 -a $y -le -0.1 ]; then cat="good";
elif [ $x -ge 5.5 -a $x -le 10.5 ] && [ $y -ge -10.9 -a $y -le -5.9 ]; then cat="bad";
fi
echo "$cat"
On that script I want to know if x is within range 0.1 till 5.5 (0.1 < x < 5.5) and y within -5.9 till -0.1 (-5.9 < y < -0.1) are true then it gives result as good
. With different boundaries it should give a bad
result.
I've run it and it gives the result as integer expression expected.
When I try to replace the operator -ge
(or -le
) with operator >
(or <
), or try to add a square bracket and anything I could think of, it gives the same error or no results are given.
How should I approach this?
Best Answer
Bash can only do integer math. If the values have a fixed number of decimal places, you can remove the
.
(usingsed
orawk
or any command you like) and compare the resulting values. For example, if they have exactly one decimal place like10.0, 0.4, 2.2
, removing the.
will multiply them by ten, resulting in100, 04, 22
(using the old test command[
, leading0
s don't matter for integer comparison). You'll have to multiply the boundaries accordingly, of course.Alternatively, you can use
bc
, which will work with arbitrary precision floating point numbers.bc
readsstdin
, so you can, for example, echo the expression and pipe it tobc
as follows:The output will be
1
if the expression istrue
,0
otherwise. Read the manual (man bc) if you want to learn more about its syntax.To incorporate this in your script, you can use command substitution like this:
Note that we still need to check if the
bc
command's output is1
, because[ 0 ]
will also evaluate totrue
.Finally, your example using
bc
:Since having those hardly readable strings inside the brackets makes it more error prone, you can use bash functions and variables like in the following example. This may be useful if you want to add additional
elif
clauses with different ranges. (Thanks to wjandrea for the useful hints)Alternative version of the
in_bounds
function usingprintf
(thanks to steeldriver):