6

In shell script how can we compare (integer and floating point) ,(flaoting point and floating point),(floating point and integer),(integer and integer) with only one if condition.

i have few examples like

 set X=3.1
  set Y=4.1
  if [ $X < $Y ] then
    echo "wassup"
  endif

But running the above from cron job doesnt seem to work.

Rajeev
  • 44,985
  • 76
  • 186
  • 285
  • Possible duplicate of [Bash: Integer expression expected](http://stackoverflow.com/questions/17958855/bash-integer-expression-expected) – tripleee Jan 20 '16 at 13:27

4 Answers4

19

The way to carry out floating point operations in bash is to use bc which is available on almost all linux distributions.

# bc will return 0 for false and 1 for true
if [ $(echo "23.3 > 7.3" | bc) -ne 0 ] 
then 
  echo "wassup"
fi

There's a good article available on linux journal about floating point math in bash using bc.

brice
  • 24,329
  • 7
  • 79
  • 95
  • 1
    i tried the following and got a error as unary operated expected – Rajeev Apr 01 '12 at 12:34
  • interesting. I have it working fine here. Hmmm. What your error means (I think) is that the `$(echo "$a > $b" | bc)` did not return a value. Can you try the subshell on its own? – brice Apr 01 '12 at 13:18
  • IE: Your variables are not properly assigned to. `echo $X` will be an empty line, for example. – brice Apr 01 '12 at 13:20
1

Bah itself only handles integers. Use bc:

echo "$X>$Y" | bc 
0
echo "$X<$Y" | bc 
1

You don't need to worry about scale. It is just for the preocision of output formats:

X=3.000001
Y=3.0001
echo "$X>$Y" | bc 
0
echo "$X<$Y" | bc 
1
echo "scale=1;$X<$Y" | bc 
1
user unknown
  • 35,537
  • 11
  • 75
  • 121
0

below example works on bash shell.

 X=3.1
 Y=4.1
 if [ $X -le $Y ]
 then
    echo "wassup"
 fi

you may want to learn shell script here

Balaswamy Vaddeman
  • 8,360
  • 3
  • 30
  • 40
  • 3
    This doesn't work here, as bash doesn't deal with floating points: `$ test "34.4" -gt "5.4" -> bash: test: 34.4: integer expression expected` – brice Mar 30 '12 at 08:51
  • 5
    I do not doubt your sincerity :) I'm just saying that this isn't guaranteed to work on Linux `bash --version` gives me `GNU bash, version 4.2.8(1)-release (x86_64-pc-linux-gnu)` – brice Mar 30 '12 at 09:04
0

EDIT. based on the comments to this answer (thanks to user unknown and glenn jackman), it seems that when using bc for a true/false test, the required bash test is simply:

  • (( $(echo "$X < $Y" |bc) )) ... see the test results and script below

wheras, the comparison to -ne 0 is needed for the old style bash [ ] test.


bash does not natively handle floating point numbers, but you can call a utility such as bc

From man bc - An arbitrary precision calculator language

X=3.1
Y=4.1
# This test has two superfluous components. 
# See EDIT (above) and TESTS below
if (($(echo "scale=9; $X < $Y" |bc)!=0)) ;then
    echo "wassup"
fi

TEST results:

if [  "1"  ]   true
   [  "1"  ]   true
if [  "0"  ]   true
   [  "0"  ]   true

if [   1   ]   true
   [   1   ]   true
if [   0   ]   true
   [   0   ]   true

if (( "1" ))   true
   (( "1" ))   true
if (( "0" ))   false
   (( "0" ))   false

if ((  1  ))   true
   ((  1  ))   true
if ((  0  ))   false
   ((  0  ))   false

echo "1<1"|bc  true
echo "1<0"|bc  true

TEST script:

printf 'if [  "1"  ]   '; if [ "1" ]; then echo true; else echo false; fi
printf '   [  "1"  ]   ';    [ "1" ]  &&   echo true  ||   echo false
printf 'if [  "0"  ]   '; if [ "0" ]; then echo true; else echo false; fi
printf '   [  "0"  ]   ';    [ "0" ]  &&   echo true  ||   echo false
echo  
printf 'if [   1   ]   '; if [  1  ]; then echo true; else echo false; fi
printf '   [   1   ]   ';    [  1  ]  &&   echo true  ||   echo false
printf 'if [   0   ]   '; if [  0  ]; then echo true; else echo false; fi
printf '   [   0   ]   ';    [  0  ]  &&   echo true  ||   echo false
echo  
printf 'if (( "1" ))   '; if (("1")); then echo true; else echo false; fi
printf '   (( "1" ))   ';    (("1"))  &&   echo true  ||   echo false
printf 'if (( "0" ))   '; if (("0")); then echo true; else echo false; fi
printf '   (( "0" ))   ';    (("0"))  &&   echo true  ||   echo false
echo  
printf 'if ((  1  ))   '; if (( 1 )); then echo true; else echo false; fi
printf '   ((  1  ))   ';    (( 1 ))  &&   echo true  ||   echo false
printf 'if ((  0  ))   '; if (( 0 )); then echo true; else echo false; fi
printf '   ((  0  ))   ';    (( 0 ))  &&   echo true  ||   echo false
echo
printf 'echo "1<1"|bc  '; echo "1<1"|bc >/dev/null  && echo true || echo false 
printf 'echo "1<0"|bc  '; echo "1<0"|bc >/dev/null  && echo true || echo false 
Peter.O
  • 6,696
  • 4
  • 30
  • 37
  • 1
    `scale` is superfluous, if you just want to test for true and false. `!=0` is superfluous too - that's what's done already. – user unknown Mar 30 '12 at 09:09
  • 1
    The `!=0` is *not* superfluous: bc *prints* 0 or 1 for false or true. In both cases, the *exit status* is zero. So, you must compare the command output to something. – glenn jackman Mar 30 '12 at 10:26
  • 1
    Nice idea, but wrong: `if (($(echo "$X > $Y" | bc))) ; then echo wassup; else echo pussaw; fi`. Reason: $(...) captures the output. ((...)) evaluates. – user unknown Mar 30 '12 at 13:30
  • It seems you are both right, *for different formats* :) ... I've added tests to my answer. – Peter.O Mar 30 '12 at 17:53
  • @glennjackman: I forgot the notification mark for you. Sorry. – user unknown Mar 30 '12 at 21:56