1

I am trying to write a script I will call calc.sh that does basic calculations using the arguments for the script ( $1, $2 and $3). For instance I'd like to get 2 as result for ./calc.sh 10 / 5

My start goes as this:

if [ $2 -eq "+" ] ; then res=`expr $1 + $3` ; echo "$res" ; fi

But it won't work, I get something like : Line 2 : [ +: an integer expression was expected

NOw That I used == to make the comparison is working fine for all the operations except the division /. The code now is:

if [ $2 == "+" ] ; then res=`expr $1 + $3` ;
elif [ $2 == "-" ] ; then res=`expr $1 - $3` ;
elif [ $2 == "x" ] ; then res=`expr $1 \* $3` ;
elif [ $2 == "/" ] ; then res=`expr $1 \/ $3` ;
else res=`Operación no válida` ;
fi ; echo "$res"

But if I try ./calc.sh 10 / 5 , I will get: "line 4: 10 / 5 : syntax error: invalid arithmetic operator (the error element is "\ 5 ")... Alas as I am typing I'm realising it should be $1 / $3 ...
:)

Thomas
  • 6,242
  • 8
  • 26
  • 32
Lorena R
  • 13
  • 4
  • 3
    `man test` ... `-eq` is for numbers, for strings you want `=`. – AlexP Nov 14 '16 at 12:15
  • Thank you! The == works, but when I use the "/" as argument it's not working. I'll try $(( $1 / $3 )) instead of expr $1 \\ $3. – Lorena R Nov 14 '16 at 12:29

4 Answers4

1

If you are using a bashshell, you can try:

if [ $2 == "+" ] ;then
 res=$(($1 + $3))
 echo $res 
fi

Edit

Change the next line (note the substitution of ' by "):

else res=`Operación no válida` ;

To:

else res="Operación no válida" ;

Edit 2

Instead of using so many if else statements, you can use a case statement:

case $2 in
+)
  res=`expr $1 + $3`
  ;;
-)
  res=`expr $1 - $3`
  ;;
/)
  res=`expr $1 \/ $3`
  ;;
x)
  res=`expr $1 \* $3`
  ;;
*)
  res="Operación inválida"
  ;;
esac

echo "$res"
Iñaki Murillo
  • 745
  • 1
  • 4
  • 14
  • 1
    Thank yo, I tried with == and is working fine except for the division symbol. if [ $2 == "+" ] ; then res=`expr $1 + $3` ; elif [ $2 == "-" ] ; then res=`expr $1 - $3` ; elif [ $2 == "x" ] ; then res=`expr $1 \* $3` ; elif [ $2 == "/" ] ; then res=`expr $1 \\ $3` ; else res=`Operación no válida` ; fi ; echo "$res" – Lorena R Nov 14 '16 at 12:26
  • Division is `/`, so replace `res=expr $1 \\ $3` with `res=$(expr $1 / $3)` – Iñaki Murillo Nov 14 '16 at 12:38
  • 1
    The final code I used worked pretty well (see in the edited question), except for the case when I don't use one of the described operators (for instance something like./calc.sh 3 r 4) I won't get the error message from the `else echo "operación inválida"`. But the question was pretty much answered. Should I do something now to signal this? – Lorena R Nov 15 '16 at 13:49
  • @LorenaR I updated my answer to address the problem with `else echo "operación inválida"`. Also, you can select the correct answer by clicking the "tick" below the two arrows – Iñaki Murillo Nov 15 '16 at 14:04
1

The script:

#!/bin/sh
IFS=" " # join arguments with a space character
echo "$* = $(( $* ))"

With + it is easy:

./calc.sh 10 + 2
10 + 2 = 12

But asterisk has to be escaped

./calc.sh 10 \* 2
10 * 2 = 20

or

./calc.sh 10 "*" 2
10 * 2 = 20
Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
hschou
  • 2,845
  • 12
  • 15
0

As @AlexP has already pointed out, you are doing arithmetic instead of a string comparison.

I would also strongly suggest that you use double brackets [[]] instead of single ones.

Your code can then be written as:

#!/bin/bash

if [[ $2 == "+" ]]; then
    echo $(($1+$3))
elif [[ $2 == "/" ]]; then
    echo $(($1/$3))
fi

Execution examples:

./math.sh 2 + 7
9
./math.sh 7 / 2
3
maulinglawns
  • 8,426
  • 2
  • 28
  • 36
  • note than you can use `=` instead of `==` as those are synonyms when using double brackets – Ikaros Nov 14 '16 at 12:36
  • Yeah, but I really prefer not to. In every other language, `=` is an assignment operator, and I like to keep it that way! – maulinglawns Nov 14 '16 at 12:37
  • = vs == is one of the methods some languages have used to distinguish between assignment and equality. There are several others like `:=` vs `=` (almost as common), `<-` vs `=`... See also https://en.wikipedia.org/wiki/Assignment_%28computer_science%29#Assignment_versus_equality. In any case the `[` command and the `[[..]]` construct have no assignment operator. – Stéphane Chazelas Nov 15 '16 at 14:32
  • Ok, I stand corrected. Every other language **I have ever used** use `=` as an assignment operator. – maulinglawns Nov 15 '16 at 17:08
0

None of +, -, x or / are special to the shell or the [ command. Your problem here is that:

  • -eq is for numeric comparison. Use = instead of string comparison
  • you forgot to quote your variables
  • == is not a standard sh [ operator

So:

if [ "$2" = + ]; then
  res=`expr "$1" + "$2"`
fi

Or use a case construct:

case $2 in
  + | - | /) res=`expr "$1" "$2" "$3"`;;
          x) res=`expr "$1" "*" "$3"`;;
          *) echo >&2 invalid; exit 1;;
esac

Note that you'd only use expr if you had to deal with ancient systems. Modern standard sh implementations have arithmetic expansions built-in via the $((...)) operator and a better form of command substitution with $(...) instead of `...`.

Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
  • Thank you for the info. I didn't know about the `expr`. From now on I will use the `$((...))` operator. – Lorena R Nov 15 '16 at 13:54