Building simple calculator in BASH - linux

I am learning Bash Shell Scripting as a section from the Linux Foundation LFS101x.2 and there is a Lab to create a simple Bash calculator.
The Lab details are found here:
Lab 5
I'm trying to run the script by:
$ ./bashShellScriptingLab5.sh s 15 5
The error message is:
Welcome to Calculator!
./bashShellScriptingLab5.sh: line 39: syntax error near unexpected token `exit'
./bashShellScriptingLab5.sh: line 39: ` exit 0'
Here is my bashShellScriptingLab5.sh:
#!/bin/bash
echo "Welcome to Calculator!"
if [ $# != 3 ];
then
echo "Usage:"
echo "Please enter a/s/m/d and two integers"
exit 1
fi
addition () {
echo "The result of adding " + $2 + " and " + $3 + " is:"
d = expr $2 + $3
echo $d
}
subtraction () {
echo "The result of subtracting " + $2 + " and " + $3 + " is:"
d = expr $2 - $3
echo $d
}
multiplication () {
echo "The result of multiply " + $2 + " and " + $3 + " is:"
d = expr $2 * $3
echo $d
}
division () {
echo "The result of dividing " + $2 + " and " + $3 + " is:"
d = expr $2 / $3
echo $d
}
if [[ "$1" = "a" ]]
then
addition()
exit 0
elif [[ "$1" = "s" ]]
then
subtraction()
exit 0
elif [[ "$1" = "m" ]]
then
subtraction()
exit 0
elif [[ "$1" = "d" ]]
then
division()
exit 0
else
echo "Usage:"
echo "Please enter a/s/m/d and two integers"
exit 1
fi

Quit a few errors here, I'll run through them and then show an example of a working script.
Firstly you appear to have made some assumptions about how functions work.
Calls to functions do not require the ()
addition()
Also you are trying to use global positional parameter in your functions which will not work as they have their own, so the call to the function should pass in what you want
addition $2 $3
With this in mind the inside of the function will also have to change
echo "The result of adding " + $1 + " and " + $2 + " is:"
As you can see we now use $1 and $2 as we are using the first and second parameter to the function,not the script!
Inside the function there are few more problems
d = expr $2 + $3
Spaces have a purpose in bash so will interfere with the = sign. The command is read as d(function/file/script/exe/whatever) and then the equals is a parameter to this. Thus you cannot have spaces between the = and both sides, so it should be written as
d=expr $2 + $3
Although this will still cause a compile error due to the spaces after expr.So we will need to run this in a subshell to assign it to d
d=$(expr $2 + $3)
Although personally i would just go for bash arithmetic
d=$(($2 + $3))
So if you change all of these in your script it should work, was gonna pad this out a bit more but ran out of time.
Working code
#!/bin/bash
echo "Welcome to Calculator!"
if [ $# != 3 ];
then
echo "Usage:"
echo "Please enter a/s/m/d and two integers"
exit 1
fi
addition () {
echo "The result of adding " + $1 + " and " + $2 + " is:"
d=$(($1 + $2))
echo $d
}
subtraction () {
echo "The result of subtracting " + $2 + " and " + $3 + " is:"
d=$(($1-$2))
echo $d
}
multiplication () {
echo "The result of multiply " + $1 + " and " + $2 + " is:"
d=$(($1*$2))
echo $d
}
division () {
echo "The result of dividing " + $1 + " and " + $2 + " is:"
d=$(($1/$2))
echo $d
}
if [[ "$1" = "a" ]]
then
addition $2 $3
exit 0
elif [[ "$1" = "s" ]]
then
subtraction $2 $3
exit 0
elif [[ "$1" = "m" ]]
then
multiplication $2 $3
exit 0
elif [[ "$1" = "d" ]]
then
division $2 $3
exit 0
else
echo "Usage:"
echo "Please enter a/s/m/d and two integers"
exit 1
fi

To call a function in bash you don't need the parens, those are what's throwing you off. Instead just do
if [[ "$1" = "a" ]]
then
addition
exit 0
elif [[ "$1" = "s" ]]
then
subtraction
exit 0
elif [[ "$1" = "m" ]]
then
multiplication
exit 0
elif [[ "$1" = "d" ]]
then
division
exit 0
else
echo "Usage:"
echo "Please enter a/s/m/d and two integers"
exit 1
fi
Also, for option "m" you had been calling subtraction again, I changed that to multiplication
That will get you past this error, I think you'll find more after that though

Simple Calculator 1.0
clear
echo "(exp=**, div=/, mult=*, add=+, sub=-)"
echo "\"a/b\" returns only quotient (use no spaces)"
echo "\"a / b\" returns quotient and remainder (use spaces)"
echo " "
echo "Welcome to my Simple Calculator"
echo " "
read -p 'Enter a simple calculation: ' -a sC
answer=$((${sC[0]} ${sC[1]} ${sC[2]}))
echo " "
echo " "
if [ "${sC[1]}" != "/" ]
then echo "The answer is equal to $answer"
else answerRemainder=$((${sC[0]} % ${sC[2]}))
echo "The answer is equal to $answer remainder $answerRemainder"
fi
echo " "
echo " "
echo "Thank you for using Simple Calculator 1.0"
echo "Have a nice day!"
No spaces between two expressions returns calculations without remainders:
(exp=**, div=/, mult=*, add=+, sub=-)
"a/b" returns only quotient (use no spaces)
"a / b" returns quotient and remainder (use spaces)
Welcome to my Simple Calculator
Enter a simple calculation: 10/4
The answer is equal to 2
Thank you for using Simple Calculator 1.0
Have a nice day!
Space between "/" will return a remainder:
(exp=**, div=/, mult=*, add=+, sub=-)
"a/b" returns only quotient (use no spaces)
"a / b" returns quotient and remainder (use spaces)
Welcome to my Simple Calculator
Enter a simple calculation: 10 / 4
The answer is equal to 2 remainder 2
Thank you for using Simple Calculator 1.0
Have a nice day!
You can make the first expression as long as you want with no spaces and multiply a second expression that contains addition, subtraction, multiplication, or division:
Enter a simple calculation: 1000/4/2/5 * 4+1
The answer is equal to 101
Enter a simple calculation: 1000/4/2/5 *4-2
The answer is equal to 98
Enter a simple calculation: 1000/4/2/5 * 4*2
The answer is equal to 200
Enter a simple calculation: 1000/4/2/5 * 4/2
The answer is equal to 50
However, Simple Calculator doesn't support remainder division of a second expression that contains any calculations not surrounded with brackets:
If dividing a second expression with calculations the second expression must be surrounded with brackets in order to obtain the correct result:
Enter a simple calculation: 1000/4/2/5 / (4/2)
The answer is equal to 12 remainder 1
Brackets for the second expression are necessary!
1000/4/2/5 / 4/2 <---no brackets will return unpredictable results.
Answer should be 12 remainder 1, but will return 3 remainder 0.
Enter a simple calculation: 1000/4/2/5 / 4/2
The answer is equal to 3 remainder 0
Here in this case for remainder division, the brackets for the second expression are necessary.

Related

How to Control Number of Parameters Entered into Function

I am trying to make a simple menu-driven calculator script. I am trying to make it such that after selecting A (add) or B (subtract) from the menu, it'll call the function and display the corresponding message when:
The parameters entered when function called is greater than 3
No parameters are entered when the function is called
The operator entered when the function is called is neither "+" or "-"
Right now it is doing the parameter check when I call the script ./mycalc.sh
executing the script
Am not sure how to make it check parameters after the function is called?
#!/bin/bash
display() {
echo "Calculator Menu"
echo "Please select an option between add, subtract or exit"
echo "A. Add"
echo "B. Subtract"
echo "C. Exit"
}
#initialize choice n
choice=n
if [[ $# -ne 3 ]]
then echo " You have not entered 3 parameters"
exit 1
fi
if [ $# -eq 0 ]
then
echo " You have not entered any parameters, please input 3. "
fi
if [[ $2 != [+-] ]]
then
echo " Please enter an add or subtract operator."
exit 1
fi
add() {
echo " The sum of $one + $three equals $(( $one $op $three ))"
}
subtract () {
echo " The difference of $one - $three equals $(( $one $op $three )) "
}
while [ $choice != 'C' ]
do display
read choice
if [ $choice = 'A' ]
then
read -p "Please enter two operands and the operator '+': " one op three
add $one $op $three
elif [ $choice = 'B' ]
then
read -p " Please enter two operands and the operator '-': " one op three
subtract $one $op $three
elif [ $choice = 'C' ]
then
echo "Thank you for using this program. The program will now exit."
fi
done
sleep 3
exit 0
if [ $# > 3 ]
then
echo " You need to input 3 parameters. "
fi
Within [...], the > is simply redirection. You'll find an empty file named 3 in your current directory.
Since this is an error condition for your script, you'll want to exit:
if [[ $# -ne 3 ]]; then
echo "usage: $0 operand1 operator operand2" >&2
exit 1
fi
And to test the operator, there are many ways.
case, but it's a bit verbose
case $2 in
'+'|'-') : ;;
*) echo "Operator must be + or -" >&2
exit 1
;;
esac
Within [[...]] the == and != operators are pattern matching operators
if [[ $2 != [+-] ]]; then
echo "Operator must be + or -" >&2
exit 1
fi

Linux While loop/ If statement query

I have a script that I cannot get to work, despite my best efforts. I really hope someone can help. Very new to programming, so still learning the ropes. I'm building an interactive shell script that requires the user to put in an operand, and then another operand, to produce the maths table for the 2nd operand. e.g. I select "+" & number "2" (from a range of 15), and it prints out the table for "2+1=3, 2+2 =4" etc. to a range of 10. Here is my current script;
#!/bin/sh
echo "Please select the function you wish to perform from the following list"
echo " Multiplication = *"
echo " Addition = +"
echo " Subtraction = -"
echo " Division = /"
echo " Exponent = ^"
read s
echo "Please select a number between 1 and 15"
read n
i = 1
while [$i ‽ le 10]
do
if [$s = "*"]
then
echo "$n x $i = $((n*i))";
elif [ $s = "+"]
echo "$n + $i = $((n+i))";
elif [$s = "-"]
echo "$n - $i = $((n-i))";
elif [$s = "/"]
echo "$n / $i = $((n/i))";
elif [$s = "^"]
echo "$n ^ $i = $((n^i))";
fi
i = $((i+1))
done
I know my while loop is incorrect, so I would really appreciate any help here! Thank you!
After some modifications :
#!/bin/sh
echo "Please select the function you wish to perform from the following list"
echo " Multiplication = *"
echo " Addition = +"
echo " Subtraction = -"
echo " Division = /"
echo " Exponent = ^"
read s
echo "Please select a number between 1 and 15"
read n
i=1
while [ "$i" -le 10 ]
do
if [ "$s" = "*" ]; then
echo "$n x $i = $((n*i))";
elif [ "$s" = "+" ]; then
echo "$n + $i = $((n+i))";
elif [ "$s" = "-" ]; then
echo "$n - $i = $((n-i))";
elif [ "$s" = "/" ]; then
echo "$n / $i = $((n/i))";
elif [ "$s" = "^" ]; then
echo "$n ^ $i = $((n^i))";
fi
i=$((i+1))
done

Linux if-else not working

i write one linux code for Fibonacci series(0 1 1 2 3 5 8) but when i run its always showing me else statement.
#!/bin/bash
#This program will show series of Fibonacci numbers upto user input.
echo -n "Enter the number for Fibonacci series: "
read num
if [ $# = 1 ]
then
x1 = 0
x2 = 1
echo "The Fibonacci series for the number $num is: "
for (( y=0;$y<num; y=$y+1 ))
do
echo -n "$x1 "
x2 = $(( $x2 + $1 ))
x1 = $(( $x2 - $x1 ))
done
else
echo "Input is wrong"
fi
if i remove if satement then i got error of line 10 and 11 and of for loop
I'm not sure why you're checking the number of arguments, but you either need to provide one argument or change it to check for zero arguments. Also you have a few spaces that will cause problems. You'll need to remove those. Lastly, as #bnaecker mentioned, you'll want to use -eq instead of = when comparing numerical equality.
#!/bin/bash
#This program will show series of Fibonacci numbers upto user input.
echo -n "Enter the number for Fibonacci series: "
read num
if [ $# = 0 ]
then
x1=0
x2=1
echo "The Fibonacci series for the number $num is: "
for (( y=0;$y<num; y=$y+1 ))
do
echo -n "$x1 "
x2=$(($x2 + $1))
x1=$(($x2 - $x1))
done
else
echo "Input is wrong"
fi

Addition of 2 numbers in shell script dynamically

I'm trying to take input from user and then based on that input either addition operation will be performed or subtraction will be performed. Choice 1 is for addition and 2 is for subtraction. The error I'm getting is this:
number.sh: line 12: d: command not found
(for addition line 12)
number.sh: line 17: d: command not found
(for subtraction line 17)
Here is the code:
#!/bin/bash
echo "enter choice"
echo "enter 1 for addition"
echo "enter 2 for subtraction"
read a
echo "entered choice is" $a
echo "now enter 2 numbers"
if [ $a = 1]; then
read b
read c
d = `expr $b + $c`
echo "addition of 2 numbers is" $d
elif [ $a = 2]; then
read b
read c
d = `expr $b - $c`
echo "subtraction of 2 numbers is" $d
else
echo "enter valid choice"
fi
You have extra spaces around your assignments and missing spaces around your [] expressions. Here's a corrected version. Note that when you use two read calls, you need a newline in between when giving the input. That is, you have to type 1 <Enter> 2 <Enter> 3 <Enter> on the command line to get a result of 5.
#!/bin/bash
echo "enter choice"
echo "enter 1 for addition"
echo "enter 2 for subtraction"
read a
echo "entered choice is" $a
echo "now enter 2 numbers"
if [ $a = 1 ]; then
read b
read c
d=`expr $b + $c`
echo "addition of 2 numbers is" $d
elif [ $a = 2 ]; then
read b
read c
d=`expr $b - $c`
echo "subtraction of 2 numbers is" $d
else
echo "enter valid choice"
fi
There should be no spaces around the = sign on line 12 and 17. Remove those spaces.
In bash, there should be no spaces around the assignment operator =.

Parameters in Linux shell script

I am trying to create a script file in Linux that acts as a basic calculator. It needs to pass 3 parameters or no parameters.
If it has 3 parameters, it should be able to execute like this.
./mycalc 1 + 2
the sum of 1 plus 2 equals 3
But if it does not have any parameters a menu should display asking for subtraction, addition, or exit.
How would this layout look? I keep trying but whenever I run it it gives me errors saying I need to enter the parameters and then after the error the menu displays.
op="$2"
if [ $op == "+" ]
then
sum=$(expr $1 + $3)
echo "The sum of $1 plus $3 equals $sum"
elif [ $op == "-" ]
then
diff=$(expr $1 - $3)
echo "The sum of $1 minus $3 equals $diff"
else
while [ $ch != "X" ] || [ $ch != "x" ]
do
read -p "C) Calculation
X) Exit" ch
Here's a "cute" answer. I'll give you some feedback on your code later.
#!/bin/bash
case $2 in
+|-) :;;
*) echo "unknown operator: $2"; exit 1;;
esac
declare -A ops=(
["-"]=minus
["+"]=plus
)
printf "%d %s %d equals %d\n" "$1" "${ops["$2"]}" "$3" "$(bc <<< "$*")"
Here's a rewrite, hopefully demonstrating a few useful techniques and good practices
#!/bin/bash
user_args () {
case $2 in
+) echo "The sum of $1 plus $3 equals $(( $1 + $3 ))" ;;
-) echo "The sum of $1 minus $3 equals $(( $1 - $3 ))" ;;
*) echo "I don't know what to do with operator '$2'" ;;
esac
}
interactive () {
PS3="Select an operator: "
select choice in plus minus exit; do
case $choice in
plus) operator="+"; break ;;
minus) operator="-"; break ;;
exit) exit;;
esac
done
read -p "First value: " first
read -p "Second value: " second
echo "The sum of $first $choice $second equals $(( $first $operator $second ))"
}
if (( $# == 3 )); then
user_args "$#"
else
interactive
fi
use of functions for modularity
case statement for easily expanded branching
select statement to generate the menu and enforce valid input
bash's built-in arithmetic expressions
passing arguments with "$#"
quoting variables everywhere the need to be quoted
Command line parameters are referenced as $1, $2, $3...
($1 for first arg, $2 for second ...)
you can test if parameters are not null with :
if [ -z "$1" ]
then
echo "No argument supplied"
fi

Resources