I am trying to compare two decimal values but I am getting errors. I used
if [ "$(echo $result1 '>' $result2 | bc -l)" -eq 1 ];then
as suggested by the other Stack Overflow thread.
I am getting errors.
What is the correct way to go about this?
You can do it using Bash's numeric context:
if (( $(echo "$result1 > $result2" | bc -l) )); then
bc will output 0 or 1 and the (( )) will interpret them as false or true respectively.
The same thing using AWK:
if (( $(echo "$result1 $result2" | awk '{print ($1 > $2)}') )); then
if echo $result1 $result2 | awk '{exit !( $1 > $2)}'; then ...awk "BEGIN {exit !(${result1} > ${result2})}" instead of piping echo into awk.if awk 'BEGIN{exit ARGV[1]>ARGV[2]}' "$z" "$y"
then
echo z not greater than y
else
echo z greater than y
fi
Following up on Dennis's reply:
Although his reply is correct for decimal points, bash throws (standard_in) 1: syntax error with floating point arithmetic.
result1=12
result2=1.27554e-05
if (( $(echo "$result1 > $result2" | bc -l) )); then
echo "r1 > r2"
else
echo "r1 < r2"
fi
This returns incorrect output with a warning although with an exit code of 0.
(standard_in) 1: syntax error
r1 < r2
While there is no clear solution to this (discussion thread 1 and thread 2), I used following partial fix by rounding off floating point results using awk followed by use of bc command as in Dennis's reply and this thread
Round off to a desired decimal place: Following will get recursive directory space in TB with rounding off at the second decimal place.
result2=$(du -s "/home/foo/videos" | tail -n1 | awk '{$1=$1/(1024^3); printf "%.2f", $1;}')
You can then use bash arithmetic as above or using [[ ]] enclosure as in following thread.
if (( $(echo "$result1 > $result2" | bc -l) )); then
echo "r1 > r2"
else
echo "r1 < r2"
fi
or using -eq operator where bc output of 1 is true and 0 is false
if [[ $(bc <<< "$result1 < $result2") -eq 1 ]]; then
echo "r1 < r2"
else
echo "r1 > r2"
fi
You can also echo an if...else statement to bc.
- echo $result1 '>' $result2
+ echo "if (${result1} > ${result2}) 1 else 0"
(
#export IFS=2 # example why quoting is important
result1="2.3"
result2="1.7"
if [ "$(echo $result1 '>' $result2 | bc -l)" -eq 1 ]; then echo yes; else echo no;fi
if [ "$(echo "if (${result1} > ${result2}) 1 else 0" | bc -l)" -eq 1 ];then echo yes; else echo no; fi
if echo $result1 $result2 | awk '{exit !( $1 > $2)}'; then echo yes; else echo no; fi
)
Can't bash force type conversion? For example:
($result1 + 0) < ($result2 + 0)
() construct runs the enclosed text as a command, it doesn't do any arithmetic. Looks like you are confusing it with the ((...)) operator.Why use bc ?
for i in $(seq -3 0.5 4) ; do echo $i ; if [[ (( "$i" < 2 )) ]] ; then echo "... is < 2";fi; done
The only problem : the comparison "<" doesn't work with negative numbers : they are taken as their absolute value.
< inside [[...]] is for string comparison (so 20 is less than 3, and 0.2 is less than 1e-50). The ('s are redundant, you can add as many as you want, they're only for grouping.
bcespecially with-lthat it's floats that are being compared. The-lisn't needed for comparisons though.