Bash script. Accept integer only if is from range - bash

I have bash script with basic arithmetic operations - Addition, Subtraction, Division and Multiplication.
#! bin/bash
input="yes"
while [[ $input = "yes" ]]
do
PS3="Press 1 for Addition, 2 for subtraction, 3 for multiplication and 4 for division: "
select math in Addition Subtraction Multiplication Division
do
case "$math" in
Addition)
echo "Enter first no:"
read num1
echo "Enter second no:"
read num2
result=`expr $num1 + $num2`
echo Answer: $result
break
;;
Subtraction)
echo "Enter first no:"
read num1
echo "Enter second no:"
read num2
result=`expr $num1 - $num2`
echo Answer: $result
break
;;
Multiplication)
echo "Enter first no:"
read num1
echo "Enter second no:"
read num2
result=`expr $num1 * $num2`
echo Answer: $result
break
;;
Division)
echo "Enter first no:"
read num1
echo "Enter second no:"
read num2
result=$(expr "scale=2; $num1/$num2" | bc)
echo Answer = $result
break
;;
*)
echo Choose 1 to 4 only!!!!
break
;;
esac
done
done
How to make that values for #num1 and #num2 are accepted only if they are numbers in certain range. For example 0 to 10. So if I enter for $num1 or $num2 lets say 500 there will be message to enter valid value?

You can create a simple function to get a number in range:
get_number() {
local lo=$1 up=$2 text=${3:-Enter a number: } num
shopt -s extglob
until
read -p "$text" num
[[ $num = ?(-)+([0-9]) ]] && (( $lo <= 10#$num && 10#$num <= $up ))
do
echo "Invalid input!" >&2
done
echo "$((10#$num))"
}
num1=$(get_number 10 15 "Enter first number: ")
num2=$(get_number -10 20) # use default prompt
Works for integers only. You might also consider inputting the numbers before the case command to avoid redundant code.

Related

Attempt when assigning a variable to add two variables within

I have tried assigning a variable to calculate two variables using addition but does not work
XML
echo "Enter 1st number"
read num1
echo "Enter 2nd number"
read num2
sum-'expr $num1 + num2'
echo "Summation = $sum"
echo "Enter no"
read num1
if test $num1 -gt 10
then
echo "Number is greater than 10"
fi
if test $num1 -1t 10
then
echo "Number is less than 10"
fi
However, this error always pops up
line 5: sum-expr $num1 + num2: command not
Please help
There are 2 errors in your implementation:
1. sum-'expr $num1 + num2' --> sum=$((num1 + num2))
2. if test $num1 -1t 10 --> if test "${num1}" -lt 10
Here is my suggestion
#!/bin/bash
echo "Enter 1st number"
read -r num1
echo "Enter 2nd number"
read -r num2
sum=$((num1 + num2))
echo "Summation = ${sum}"
echo "Enter no"
read -r num1
if test "${num1}" -gt 10
then
echo "Number is greater than 10"
fi
if test "${num1}" -lt 10
then
echo "Number is less than 10"
fi

For bash scripting

#!/bin/bash
read –p “Enter the number you seek ” NUM
for VALUE in $#; do
if [ $VALUE –eq $NUM ]; then COUNT=$((COUNT+1)); fi
done
echo $NUM appeared $COUNT times
Can the above script be modified so that :
input two inputs from the user, instead of just NUM, and count the number of parameters that are equal to or in between the two. For instance, if the user inputs 12 and 20, we would have 5 matches (12, 18, 19, 12, 18). Assume the first input is less than the second (that is, you do not need to worry about the user inputting 20 and then 12)
This is what i am coming up with:
#1/bin/bash
read - p "Enter two numbers ' NUM1 NUM2
for VALUE in $#; do
if [$VALUE <= $NUM1 ] && [ $VALUE => $NUM2 ]; then COUNT=$((COUNT+1))
fi
done
echo we have $COUNT numbers between $NUM1 and $NUM2, including $NUM1 and $NUM2
#1 is a typo for #!.
You need a space after [.
Your conditions are backwards. When value is between num1 and num2, it's greater than or equal to num1, but you have less than or equal.
The numeric comparison tests are -ge and -le, since > and < are I/O redirection operators in shell scripts.
You have to use balanced quotes around a string; if it starts with " it has to end with ", not '.
You should always quote variables unless you have a specific need to allow word splitting of the expansion.
#!/bin/bash
COUNT=0
read - p "Enter two numbers " NUM1 NUM2
for VALUE in "$#"; do
if [ "$VALUE" -ge "$NUM1" ] && [ "$VALUE" -le "$NUM2" ]; then COUNT=$((COUNT+1))
fi
done
echo "we have $COUNT numbers between $NUM1 and $NUM2, including $NUM1 and $NUM2"

If else condition in addition. Defining the range

I want to write a program which can add two numbers.
The program should contain the if else condition which can describe the range of numbers.
This is what i have done so far:
Echo"enter two numbers "
Read num1 num2
Sum=$((num1 + num2))
Echo" The sum is = $sum"
As you can see, your problems were all typographical errors.
echo "enter two numbers "
read num1 num2
if [ $num1 -lt 0 ] ; then
echo num1 out of range
exit
fi
if [ $num2 -lt 0 ] ; then
echo num2 out of range
exit
fi
sum=$((num1 + num2))
echo " The sum is = $sum"

Division by zero using shell

I'm writing a shell program using while commands to prevent division by zero and to exit the program when the user types 99. Everytime i run it i get an error for the input of the second number which in turn does not give me the answer. Below is my attempt at this problem:
#!/bin/bash
firstNum=0
secondNum=0
answer=0
while true firstNum != 99, secondNum != 99 do
read -p "Enter first number" firstNum
read -p "Enter second number" secondNum
echo "first num $firstNum"
echo "second Num $secondNum"
if ["$secondNum" = "0"]
then
exit 1
else
echo "first number / second Number = $((firstNum/secondNum))"
echo "Answer = $answer"
fi
do
exit
done
And the following is the error message that i get
./example.sh: 10: ./example.sh: [2: not found
Any help at all is greatly appreciated.
Thanks
Looks like a few typos.
Replace this:
if ["$secondNum" = "0"] then
exit 1
then
echo "1st number / 2nd number = $((firstNum/secondNum))"
echo "Answer = $answer"
fi
with this:
if [ "$secondNum" = "0" ]
then
exit 1
else
echo "1st number / 2nd number = $((firstNum/secondNum))"
echo "Answer = $answer"
fi
Bash is finicky. Ensure then is on the next line and not same line as the if, you also had then instead of else on your 3rd line.
Your code can be simplified
while true; do
read -p "Enter first number: " firstNum
[[ "$firstNum" -eq 99 ]] && break
read -p "Enter second number: " secondNum
case "$secondNum" in
99) break ;;
0) echo "div by zero, try again"; continue ;;
esac
echo "first number / second Number = $(bc -l <<< "$firstNum/$secondNum")"
done
I'm calling out to bc to get floating point arithmetic. With the shell you're limited to integers only.
<<< is a "here-string", a string to pass to bc's stdin
Your code looks pretty good to me, but I changed the POSIX shell test around a bit to test for values less than 99 instead of 99 itself. And there was a stray do near the bottom of the script which I removed. Bash has [[]] style test syntax too which you may want to switch to at some point.
#!/bin/bash
firstNum=0
secondNum=0
answer=0
while [ "$firstNum" -lt 99 -a "$secondNum" -lt 99 ]
do
read -p "Enter first number " firstNum
read -p "Enter second number " secondNum
printf "first num $firstNum\n"
printf "second Num $secondNum\n"
if [ "$secondNum" = 0 ]
then
printf "$secondNum was a zero, exiting!\n"
exit 1
else
printf "first num / second Num = \$(($firstNum / $secondNum))\n"
answer=$(( firstNum / secondNum))
printf "Answer = $answer\n"
fi
done
If you are interested in learning the Bash test syntax [[]] (it's a bit more powerful than POSIX shell's test(1) []) here is an example which uses it:
#!/bin/bash
firstNum=0
secondNum=0
answer=0
while [[ "$firstNum" < 99 && "$secondNum" < 99 ]]
do
read -p "Enter first number " firstNum
read -p "Enter second number " secondNum
printf "first num $firstNum\n"
printf "second Num $secondNum\n"
if [[ "$secondNum" == 0 ]]
then
printf "$secondNum was a zero, exiting!\n"
exit 1
else
printf "first num / second Num = \$(($firstNum / $secondNum))\n"
answer=$(( firstNum / secondNum))
printf "Answer = $answer\n"
fi
done
It may also be advisable to move the tests into the body of the while loop and instead use the convention 'while [[ 1 ]]' to create a continuous loop. Here is an example doing that (using bash test syntax [[]]) and using bc so the script supports floating point arithmetic:
#!/bin/bash
firstNum=0
secondNum=0
answer=0
while [[ 1 ]]
do
read -p "Enter first number " firstNum
read -p "Enter second number " secondNum
printf "first num $firstNum\n"
printf "second Num $secondNum\n"
case "$firstNum" in
99) printf "Invalid values\n"
exit 1
;;
esac
case "$secondNum" in
99) printf "Invalid values\n"
exit 1
;;
0) printf "Invalid values\n"
exit 1
;;
esac
answer=$(printf "$firstNum / $secondNum\n" | bc -l)
printf "Floating point supported answer using bc: = $answer \n"
done

Creating a calculator script

I am trying to make a calculator with a bash script.
The user enters a number, chooses whether they wish to add, subtract, multiply or divide. Then the user enters a second number and is able to choose whether to do the sum, or add, subtract, multiply or divide again on a loop.
I cannot rack my head around this right now
echo Please enter a number
read number
echo What operation would you like to perform: 1: Add, 2: Subtract, 3: Multiple, 4: Divide
read operation
case $operation in
1) math='+';;
2) math='-';;
3) math='*';;
4) math='/';;
*) math='not an option, please select again';;
esac
echo "$number $math"
echo Please enter a number
read number2
echo What operation would you like to perform: 1: Add, 2: Subtract, 3: Multiple, 4: Divide, 5: Equals
read operation2
case $operation2 in
1)math2='Add';;
2)math2='Subtract';;
3)math2='Multiply';;
4)math2='Divide';;
5)math2='Equals';;
*)math2='not an option, please select again';;
esac
echo You have selected $math2
exit 0
This is what I have done so far, but can anyone help me work out how to loop back on the calculator?
The lesser-known shell builtin command select is handy for this kind of menu-driven program:
#!/bin/bash
while true; do
read -p "what's the first number? " n1
read -p "what's the second number? " n2
PS3="what's the operation? "
select ans in add subtract multiply divide; do
case $ans in
add) op='+' ; break ;;
subtract) op='-' ; break ;;
multiply) op='*' ; break ;;
divide) op='/' ; break ;;
*) echo "invalid response" ;;
esac
done
ans=$(echo "$n1 $op $n2" | bc -l)
printf "%s %s %s = %s\n\n" "$n1" "$op" "$n2" "$ans"
done
Sample output
what's the first number? 5
what's the second number? 4
1) add
2) subtract
3) multiply
4) divide
what's the operation? /
invalid response
what's the operation? 4
5 / 4 = 1.25000000000000000000
If I was going to get fancy with bash v4 features and DRY:
#!/bin/bash
PS3="what's the operation? "
declare -A op=([add]='+' [subtract]='-' [multiply]='*' [divide]='/')
while true; do
read -p "what's the first number? " n1
read -p "what's the second number? " n2
select ans in "${!op[#]}"; do
for key in "${!op[#]}"; do
[[ $REPLY == $key ]] && ans=$REPLY
[[ $ans == $key ]] && break 2
done
echo "invalid response"
done
formula="$n1 ${op[$ans]} $n2"
printf "%s = %s\n\n" "$formula" "$(bc -l <<< "$formula")"
done
Wrapping Code in a Loop
If you just want to wrap your code in a Bash looping construct, and are willing to hit CTRL-C to terminate the loop rather than do something more fancy, then you can wrap your code in a while-loop. For example:
while true; do
: # Your code goes here, inside the loop.
done
Just make sure to move your unconditional exit statement out of the body of the loop. Otherwise, the loop will terminate whenever it reaches that line.
For your ~/.bashrc:
alias bc="BC_ENV_ARGS=<(echo "scale=2") \bc"
Just use bc, with that alias it automatically works with two decimals instead of integers.
!/bin/bash
PS3="what's the operation? "
declare -A op=([add]='+' [subtract]='-' [multiply]='*' [divide]='/')
while true; do
read -p "what's the first number? " n1
read -p "what's the second number? " n2
select ans in "${!op[#]}"; do
for key in "${!op[#]}"; do
[[ $REPLY == $key ]] && ans=$REPLY
[[ $ans == $key ]] && break 2
done
echo "invalid response"
done
formula="$n1 ${op[$ans]} $n2"
printf "%s = %s\n\n" "$formula" "$(bc -l <<< "$formula")"
done
Please use the following script.
clear
sum=0
i="y"
echo " Enter one no."
read n1
echo "Enter second no."
read n2
while [ $i = "y" ]
do
echo "1.Addition"
echo "2.Subtraction"
echo "3.Multiplication"
echo "4.Division"
echo "Enter your choice"
read ch
case $ch in
1)sum=`expr $n1 + $n2`
echo "Sum ="$sum;;
2)sum=`expr $n1 - $n2`
echo "Sub = "$sum;;
3)sum=`expr $n1 \* $n2`
echo "Mul = "$sum;;
4)sum=`expr $n1 / $n2`
echo "Div = "$sum;;
*)echo "Invalid choice";;
esac
echo "Do u want to continue ?"
read i
if [ $i != "y" ]
then
exit
fi
done
#calculator
while (true) # while loop 1
do
echo "enter first no"
read fno
if [ $fno -eq $fno 2>/dev/null ]; # if cond 1 -> checking integer or not
then
c=1
else
echo "please enter an integer"
c=0
fi # end of if 1
if [ $c -eq 1 ]; #if 2
then
break
fi # end of if 2
done # end of whie 1
while(true) #while loop 2
do
echo "enter second no"
read sno
if [ $sno -eq $sno >/dev/null 2>&1 ] # if cond 3 -> checking integer or not
then
c=1
else
echo "please enter an integer"
c=0
fi # end of if 3
if [ $c -eq 1 ] # if cond 4
then
break
fi # end of if 4
done #2
while(true) # while loop 3
do
printf "enter the operation (add,div,mul,sub) of $fno and $sno\n"
read op
count=0
##addition
if [ $op = add ] #if cond 5
then
echo "$fno+$sno is `expr $fno + $sno`"
#multiplication
elif [ $op = mul ];
then
echo "$fno*$sno is `expr $fno \* $sno`"
#substraction
elif [ $op = sub ]
then
while(true) #while loop 3.1
do
printf "what do you want to do??? \n 1. $fno-$sno \n 2. $sno-$fno"
printf "\n press the option you want to perform?(1 or 2)\n"
read opt
if [ $opt = 1 ] #if cond 5.1
then
echo "$fno-$sno is `expr $fno - $sno`"
break
elif [ $opt = 2 ]
then
echo " $sno-$fno is `expr $sno - $fno`"
break
else "please enter valid options to proceed(1 or 2)";
clear
fi #end of if 5.1
done # end of 3.1
#division
elif [ $op = div ]
then
while(true) # whilw loop 3.2
do
printf "what do you want to do??? \n 1. $fno/$sno \n 2. $sno/$fno"
printf "\n press the option you want to perform?(1 or 2)\n"
read opt
if [ $opt = 1 ] #if cond 5.2
then
echo "$fno divided by $sno is `expr $fno / $sno`"
break
elif [ $opt = 2 ]
then
echo " $sno divided by $fno is `expr $sno / $fno`"
break
else
clear
fi #end of if 5.2
done # end of 3.2
else
echo "valid option please!!!"
count=1
fi # end of if 5
if [ $count -eq 0 ] #if cond 6
then
echo "Do you want to do more ops"
echo "(y/n)"
read ans
clear
if [ $ans = n ] # if 6.1
then
break
fi # end of if 6.1
fi #end of if 6
done #end of while 3

Resources