Reputation: 99
I'm trying to test if the variable $test
is between -0.9
and 0.9
. The following code works with numbers, but if $test
is a lower case letter, it says it's a number between -0.9
and 0.9
.
Is there a better way of doing this, so that letters are not considered to be in the range?
test=a
if (( $( echo "$test >= -0.9" |bc -l) )) && (( $(echo "$test <= 0.9" |bc -l) )); then
echo "${test} is between -0.9 and 0.9"
else
echo "${test} is NOT between -0.9 and 0.9"
fi
Upvotes: 2
Views: 1333
Reputation: 189628
Refactoring the code to use Awk might be more efficient, though it requires understanding some obscure things about the shell.
if awk -v number="$test" 'END { exit !( \
number !~ /[^0-9.]/ && number !~ /\..*\./ && \
number >= -0.9 && number <= 0.9) }' /dev/null
then
echo "$test is between -0.9 and 0.9"
else
echo "$test is NOT between -0.9 and 0.9"
fi
The exit code examined by if
is regarded as true if it's zero, which is opposite to the truth value inside the parentheses; thus exit !(...)
. Awk's processing model requires you to read an input file; we supply /dev/null
, and put the actual logic in the END
block so it gets executed even when there is no input.
This checks that there is never more than one decimal point but the regex doesn't currently cope with exponential notation. Adding support for that should not be too hard, given the regex in John1024's answer.
Upvotes: 0
Reputation: 113914
Replace:
if (( $( echo "$test >= -0.9" |bc -l) )) && (( $(echo "$test <= 0.9" |bc -l) )); then
With (assuming GNU or other enhanced bc):
if [[ "$test" =~ ^[[:digit:].e+-]+$ ]] && echo "$test>-0.9 && $test <=0.9" |bc -l | grep -q 1; then
[[ "$test" =~ ^[[:digit:].e+-]+$ ]]
This checks that $test
contains only legal number characters.
&&
This continues the bc test only if $test
passed the number check.
echo "$test>-0.9 && $test <=0.9" |bc -l | grep -q 1
This verifies that $test
is in the range that you want. grep -q 1
sets the appropriate exit code for the if
statement to use.
Upvotes: 1