0

I'm making a script for a class that should be asking you to enter two whole numbers and then ask you to select a / s / m / d for add, subtract multiply or divide. It will also make sure you entered a whole number and a valid option but I'll work on that later. For now here is what I have:

#!/bin/bash
echo "Please input a whole number"
read num1
echo "Please input another whole number"
read num2
echo "Please input funtion: [a] for addition, [s] for subtraction, [m] for multiply, or [d] for divide"
read func

if [ "$func" -eq "a" ]; then echo $((num1 + num2)) fi

if [ "$func" -eq "s" ]; then echo $((num1 - num2)) fi

if [ "$func" -eq "m" ]; then echo $((num1 * num2)) fi

if [ "$func" -eq "d" ]; then echo $((num1 / num2)) fi

else echo "Please select only [a] for addtion, [s] for subtration, [m] for multiply, or [d] for divide"


When I run it, it asks for the things correctly but I'm getting errors I'm not understanding:

./MathTest.sh: line 9: [: a: integer expression expected
./MathTest.sh: line 13: [: a: integer expression expected
./MathTest.sh: line 17: [: a: integer expression expected
./MathTest.sh: line 21: [: a: integer expression expected
./MathTest.sh: line 25: syntax error near unexpected token `else'
./MathTest.sh: line 25: `else'

Would anyone give me a hand with this please?

Chris Davies
  • 116,213
  • 16
  • 160
  • 287

1 Answers1

5
  1. you need to use a string comparison (=) instead of an integer comparison (eq).

  2. The else statement in your script has no corresponding if statement. If you want to do a series of if/then/else if/then/.../else statements, you need to either use if ... elif ... elif .... else ... fi ... instead of if ... fi; if ... fi; if ... fi; else OR use a case statement.

    In case it's not obvious, elif means else if.

    For example:

#!/bin/bash
echo "Please input a whole number"

read num1

echo "Please input another whole number"

read num2

echo "Please input funtion: [a] for addition, [s] for subtraction, [m] for multiply, or [d] for divide"

read func

case "$func" in a) echo $((num1 + num2)) ;; s) echo $((num1 - num2)) ;; m) echo $((num1 * num2)) ;; d) echo $((num1 / num2)) ;; *) echo "Please select only [a] for addtion, [s] for subtration, [m] for multiply, or [d] for divide" ;; esac

Note that the code for each case needs to be terminated with two semi-colons ;; - that's because each case can have multiple code statements (separated by either newlines or single semi-colons), so the shell interpreter needs some way of distinguishing between just another statement for this case and the end of the case, and ;; is what it uses to do this.

A simple example showing two statements per case:

case "$func" in
  a) echo "addition:"    ; echo $((num1 + num2)) ;;
  s) echo "subtraction:" ; echo $((num1 - num2)) ;;
...
esac

Instead of the case statement (which IMO, makes for much more readable code - and certainly shorter, less repetitive code), you could use if/elif/else/fi, like so:

if [ "$func" = "a" ]; then
  echo $((num1 + num2))
elif [ "$func" = "s" ]; then
  echo $((num1 - num2))
elif [ "$func" = "m" ]; then
  echo $((num1 * num2))
elif [ "$func" = "d" ]; then
  echo $((num1 / num2))
else
  echo "Please select only [a] for addtion, [s] for subtration, [m] for multiply, or [d] for divide"
fi 

Note that this is using = instead of -eq for the comparisons (because it's comparing strings, not numbers) and that it's one long chain of if, elif, elif, elif, else, fi statements, not individual if ... fi statements.

BTW, there's a very important difference between an if/elif/fi chain and multiple if ... fi statements. With if/elif/elif/elif/.../else/fi, only the code in the first true result will ever execute (or the else code if none of them are true), and the shell will skip to the end of the entire chain, similar to how a case ... esac statement works.

With multiple if ... fi statements, each one will be evaluated in turn and every one that evaluates to true will be executed, independently of all the other tests.

cas
  • 78,579
  • Thanks so much! It worked exactly like you said and even better, I understand what I did wrong. There are a couple more bits to work on to round out the script (have to put in code to make sure the number entered is a whole number) so this is great!! – Geordie Calhoun Dec 07 '21 at 13:55
  • Ok, I put in the next steps, to check and see if the number is in actual number (not a letter) and if it isn't, echo a statement and exit the script. ShellCheck says the code is good (that's a plus) but if you enter a number, it acts as if you entered a letter and just exists. – Geordie Calhoun Dec 07 '21 at 18:55
  • you should post a new question (don't add your new question to this one, that's not how stackexchange works) – cas Dec 08 '21 at 01:56