1

I wrote a bash script that reads a variable from a textfile using:

XX=`sed -n -e ''"$row"'p' $filename | awk '{print $4}'`

echo $XX
12.88

then I want to test whether this number is greater than 12.5. If it is, then the variable ex should be set to 1200.

if [ "$XX" -ge 12.5 ]
    then
        ex=1200
else
    echo boo

fi

When I run this script I get the following error:

[: 12.88: integer expression expected

When I debug my code, it seems the variable is being assigned correctly. Here's the output:

+ echo 12.88
12.88
+ '[' 12.88 -ge 12.5 ']'
./test.sh: line 33: [: 12.88: integer expression expected

What am I doing wrong?

aloha
  • 4,554
  • 6
  • 32
  • 40

1 Answers1

4

The bash shell does not do floating point, it's strictly concerned with integral values (and strings of course, but that's another matter). From the bash man page (my italics):

arg1 OP arg2 - OP is one of -eq, -ne, -lt, -le, -gt, or -ge. These arithmetic binary operators return true if arg1 is equal to, not equal to, less than, less than or equal to, greater than, or greater than or equal to arg2, respectively. Arg1 and arg2 may be positive or negative integers.

You can do these sorts of comparisons using a tool like bc, which does understand floating point:

pax$ if (( $(bc <<<'3.14159 > 2.71828') )) ; then
...>    echo pi is greater than e
...> else
...>    echo pi is not greater than e
...> fi
pi is greater than e

pax$ if (( $(bc <<<'3.14159 < 2.71828') )) ; then
...>    echo pi is less than e
...> else
...>    echo pi is not less than e
...> fi
pi is not less than e

This works because bc can take a floating point comparison and gives you 1 if it's true, 0 otherwise.

In case of needing comparison with a variable, make sure you use double quotes so the variable is interpreted:

xx=3.14
pax$ if (( $(bc <<<"$xx < 2.71828") )) ; then
...>    echo xx is less than e
...> else
...>    echo xx is not less than e
...> fi
xx is not less than e

You can also include arbitrary expression within bc and have bash just interpret the comparison result of 0 or 1:

pax$ xx=4 ; if (( $(bc <<<"$xx < 5 || $xx > 7") )) ; then echo not 4-6 ; fi
not 4-6
pax$ xx=5 ; if (( $(bc <<<"$xx < 5 || $xx > 7") )) ; then echo not 4-6 ; fi
pax$ xx=9 ; if (( $(bc <<<"$xx < 5 || $xx > 7") )) ; then echo not 4-6 ; fi
not 4-6
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • I already tried this command `if (( $(bc <<<'$XX < 12.5') )); then echo bla` and I tried the command you just gave me. I got the following error `(standard_in) 1: illegal character: $ (standard_in) 1: illegal character: X` – aloha Dec 08 '16 at 01:51
  • 1
    @aloha, if you use *single* quotes `'`, environment variables won't be substituted and the `$` will be given as-is to `bc`. Try using double quotes `"`: `xx=10 ; if (( $(bc <<<"$xx < 12.5") )); then echo bla ; fi` – paxdiablo Dec 08 '16 at 01:53
  • it worked with `"` though I didn't quiet understand why. I guess I need to understand how `bash` operates. – aloha Dec 08 '16 at 01:55
  • 1
    @aloha: because double quotes allow variable expansion, single quotes don't :-) – paxdiablo Dec 08 '16 at 01:57
  • what if I want to write something like this ` if (( $(bc <<<"$XX -ge 12.5") )) && (( $(bc <<<"$XX -le 13") ))` I get an error `(standard_in) 1: parse error` as in `XX>=12.5 and XX<=13` – aloha Dec 08 '16 at 02:06
  • @aloha, you do *that* in `bc` as well, see the update... – paxdiablo Dec 08 '16 at 02:11