shell script * operation gives too many arguments - bash

I m doing a simple calculator with option of choosing to continue or not . But when I try multiplying operation I get error in the console :
calculator.sh: line 17: [: too many arguments
calculator.sh: line 22: [: too many arguments
calculator.sh: line 27: [: too many arguments
calculator.sh: line 32: [: too many arguments
Which basically means all my operations has this error , but that is not true when I use them , they act normally .
I searched in stack overflow for similarities , but the examples are different . I escaped the * with slash , but I think it shouts the error in the comparing with the character "*" in order getting to the body of the if statement.
Here is the code:
#!/bin/bash
choice="Y"
while [ $choice == "Y" ]
do
echo -n "Enter first value:"
read firstvar
echo -n "Enter second value:"
read secondvar
echo -n "Enter last value:"
read compvar
echo -n "Enter operation:"
read ops
counter=0
result=0
while [ $result != $compvar ]
do
if [ $ops == "+" ]
then result=$((firstvar+secondvar))
echo "Do you want to continue ? Y/N"
read choice
break
elif [ $ops == "-" ]
then result=$((firstvar-secondvar))
echo "Do you want to continue ? Y/N"
read choice
break
elif [ $ops == "*" ]
then result=$((firstvar\*secondvar))
echo "Do you want to continue ? Y/N"
read choice
break
elif [ $ops == "/" ]
then result=$((firstvar/secondvar))
echo "Do you want to continue ? Y/N"
read choice
break
else
echo "Input valid operation !!!"
echo "Do you want to continue ? Y/N"
read choice
break
fi
counter=$((counter+1))
done
done

The problem is likely not because the "*" in script, but because of an asterisk in your $ops variable.
You should double-quote the variables to avoid globbing being applied to them; rewrite your tests like this:
elif [ "$ops" = "*" ]
Here's a very helpful resource for checking your shell scripts.

First, see the comment by Charles Duffy WRT "==" vs "=" for string tests.
Change occurrences of $ops to "${ops}".
Remove the escape in result=$((firstvar*secondvar)).
I took the liberty to reformat the script just a bit.
Hope this helps.
#!/bin/bash
choice="Y"
while [ $choice = "Y" ]
do
echo -n "Enter first value:"
read firstvar
echo -n "Enter second value:"
read secondvar
echo -n "Enter last value:"
read compvar
echo -n "Enter operation:"
read ops
counter=0
result=0
while [ $result != $compvar ]
do
if [ "${ops}" = "+" ]; then
result=$((firstvar+secondvar))
echo "Do you want to continue ? Y/N"
read choice
break
elif [ "${ops}" = "-" ]; then
result=$((firstvar-secondvar))
echo "Do you want to continue ? Y/N"
read choice
break
elif [ "${ops}" = "*" ]; then
result=$((firstvar*secondvar))
echo "Do you want to continue ? Y/N"
read choice
break
elif [ "${ops}" = "/" ]; then
result=$((firstvar/secondvar))
echo "Do you want to continue ? Y/N"
read choice
break
else
echo "Input valid operation !!!"
echo "Do you want to continue ? Y/N"
read choice
break
fi
counter=$((counter+1))
done
done

Related

Bash: Why does variable containing string a equate to string b in an if statement?

I set a prompt to get user input Yy/Nn. Then I check if the response matches Y/y or N/n. However everytime it evaluates to true on "$prompt_1"="Y"/"y" even when you answer N/n. Now I am sure there is a reason why, however searching around brought me to a few solutions IG: Qoutes around the variables. But nothing has helped to resolve this.
#!/bin/bash
clear;
echo "Would you like to proceed with installation?"
read prompt_1;
echo $prompt_1;
if [ "$prompt_1"="Y" ] || [ "$prompt_1"="y" ]; then
echo "You've accepted installation";
elif [ "$prompt_1”="N"] || [ “$prompt_1"="n" ]; then
exit;
fi
You need to add spaces around the = operator:
if [ "$prompt_1" = "Y" ] || [ "$prompt_1" = "y" ]; then
echo "You've accepted installation";
elif [ "$prompt_1" = "N" ] || [ "$prompt_1" = "n" ]; then
exit;
fi
Or using the pattern-matching operator =~ in a [[...]] expression:
if [[ "$prompt_1" =~ ^[Yy]$ ]]; then
echo "You've accepted installation";
elif [[ "$prompt_1" =~ ^[Nn]$ ]]; then
exit
fi
The case statement solution.
case $prompt_1 in
[Yy]) echo "You've entered $prompt_1 and accepted installation."
##: do something here
;;
[Nn]) echo "You entered $prompt_1 and did not accepted the installation."
exit
;;
*|'') echo "Unknown option ${prompt_1:-empty}." ##: not [Nn] or [Yy] or empty.
exit
;;
esac
That is not restricted to bash anymore, it should work on other POSIX sh shells too.
Another suggestion, using case and lower case substitution:
case ${prompt_1,,} in
y|yes|"just do it")
echo "You've accepted installation"
# perform installation
;;
n|no|forget) exit;;
*) echo "Wrong answer, try again";;
esac
PS: Works in bash4 or later.

Return to previous commands in bash script?

I'm trying to implement a prev option in my bash script to go back to the previous "menu", as well as a way for the script to ask for user input again if no variable is set for $name.
Heres my bash script:
#!/bin/bash
#Menu() {
for (( ; ; ))
do
beginORload=
echo "Choose option:"
echo "1 - Begin"
echo "2 - Load"
read -p "?" beginORload
#}
#Begin() {
if [ "$beginORload" -eq "1" ]
then
clear
for (( ; ; ))
do
echo "Beginning. What is your name?"
read -p "?" name
#If "prev" specified, go back to #Menu()
if [ "$name" -eq "prev" ]
then
Menu
fi
#If nothing specified, return to name input
if [ -z ${name+x} ]
then
Begin
else
break
fi
echo "Hi $name !"
done
fi
done
In batch, I could simply do:
:menu
echo Choose option:
echo 1 - Begin
echo 2 - Load
[...]
:begin
[...]
if "%name%==prev" goto menu
if "%name%==" goto begin
the issue is I keep running into errors all over the place, and I can't figure out what to type to get it to work
im running Yosemite btw. Thankyou
Something like this is close to what you expect:
while [[ $answer -ne '3' ]];do
echo "Choose option:"
echo "1 - Begin"
echo "2 - Load"
echo "3 - Exit"
read -p "Enter Answer [1-2-3]:" answer
case "$answer" in
1) while [[ "$nm" == '' ]];do read -p "What is your Name:" nm;done # Keep asking for a name if the name is empty == ''
if [[ $nm == "prev" ]];then nm=""; else echo "Hello $nm" && break; fi # break command breaks the while wrapper loop
;;
2) echo 'Load' ;;
3) echo 'exiting...' ;; # Number 3 causes while to quit.
*) echo "invalid selection - try again";; # Selection out of 1-2-3 , menu reloaded
esac # case closing
done # while closing
echo "Bye Bye!"
As a general idea you can wrap up your case selection in a while loop which will break under certain circumstances (i.e If Option 3 is selected or if a valid name is given (not blank - not prev)
PS1: In bash you compare integers with -eq , -ne, etc but you compare strings with == or !=
PS2: Check the above code online here

if statement shell script error

Hello I don't know if this will be a duplicate , but I really don't see the error in this piece of code . It gives me an error at the then statement and I think there is no error .
I have putted comments on the two lines where the code breaks .
Here is the code:
#!/bin/bash
echo -n "Enter first value:"
read firstvar
echo -n "Enter second value:"
read secondvar
echo -n "Enter last value:"
read compvar
echo -n "Enter operation:"
read ops
counter=0
result=0
while [ $result -eq $compvar ]
do
if [ $ops -eq "+" ]
then result = $((firstvar+secondvar))
elif [ $ops -eq "-" ]
then result = $((firstvar-secondvar))
#elif[ $ops -eq "*" ]
#then result = $((firstvar\*secondvar))
#elif[ $ops -eq "/" ]
#then result = $((firstvar/secondvar))
else
echo "Input valid operation !!!"
fi
(($counter++))
done
Oh shoot , I m retarded . Missed the space between "elif" and the "[" .
You need to learn how to space and indent to have your code legible.
#!/bin/bash
echo -n "Enter first value:"; read firstvar
echo -n "Enter second value:"; read secondvar
echo -n "Enter last value:"; read compvar
echo -n "Enter operation:"; read ops
counter=0; result=0 #initialize variables
while [ $result -eq $compvar ]; do
if [ $ops = "+" ]; then
result = $((firstvar+secondvar))
elif [ $ops = "-" ]; then
result=$((firstvar-secondvar))
else
echo "Input valid operation !!!"
fi
((++counter))
done
Writing code is the same as writing literature. There are forms to use to make it easy for the reader (even if it's just you 6 months later) to follow. Your code above is confusing, and will bite you on the butt later. Add comments to.
The while loop is gratuitous and will do nothing-- the -eq should at least be -ne. The counter could be initialized as an integer to avoid problems that could arise, but it's also never used.

Bash if blocking elif

I am trying to write a calculator script but the first if blocks the elif. What I mean is when I try to run it I press 1 but it runs as if I pressed 2. Here is my code.
echo "For Advanced mode press 1"
echo "For Help press 2"
loop=1
while [ $loop=1 ]; do
read n
if [ $n=2 ]; then
echo "To use the calculator follow the promptings."
echo "If asked, the operators are: "
echo "* for multiplication, / for division."
echo "+ for addition, - for subtraction."
echo "% for modulus, which is division remainder"
echo "== is equal to, != is not equal to."
echo "** for exponents"
n=""
elif [ $n=1 ]; then
read a
break
fi
done
echo "_______________________"
echo "What would you like to do?"
echo "Press 1 for basic arith"
echo -n "Press 2 for geometry"
read choice
loop=2
if [ $choice=1]; then
while [ $loop=2 ]; do
echo -n "Enter X Value: "
read x
echo -n "Enter Operator: "
read op
echo -n "Enter Y Value: "
read y
ans=$((x $op y))
echo "$x $op $y = $ans"
echo "____________________"
echo "To input a new function, press enter"
read cont
done
fi
The [ built-in is used for evaluating conditions. There must be a space after the opening [ and a space before before the closing ], otherwise it's incorrect syntax.
Inside a [ ... ] expression, you can use various conditional operators. One such operator is =. You must put spaces before and after an operator, otherwise it's not recognized as an operator.
For example, [ $n=2 ] where the value of n is 1, will be evaluated as [ 1=2 ]. The 1=2 is not evaluated as a condition, because there are no spaces around it. The 1=2 will be evaluated as a string "1=2". And any non empty string in Bash is truthy, so the statement [ 1=2 ] yields true, even if it doesn't "look like" it would be true.
You must write [ "$n" = 2 ] so that = is interpreted as the conditional operator, and the expression doesn't become a single string. Note that spaces are extremely important in Bash. Spaces separate the logical elements of a program, without spaces expressions are concatenated as strings.
Also notice that I added double quotes around the variable. This is to protect the expression in case the variable is empty. If for example you write [ $n = 2 ] and the variable is empty, then the expression will be evaluated as [ = 2 ], which is a malformed expression, and the script will crash with an error.
Put spaces between your condition elements like $n = 2 not $n=2.You should pass it's arguments as whitespace separated words. So your code should be as following:
echo "For Advanced mode press 1"
echo "For Help press 2"
loop=1
while [ $loop = 1 ]; do
read n
if [ $n = 2 ]; then
echo "To use the calculator follow the promptings."
echo "If asked, the operators are: "
echo "* for multiplication, / for division."
echo "+ for addition, - for subtraction."
echo "% for modulus, which is division remainder"
echo "== is equal to, != is not equal to."
echo "** for exponents"
n=""
elif [ $n = 1 ]; then
read a
break
fi
done
echo "_______________________"
echo "What would you like to do?"
echo "Press 1 for basic arith"
echo -n "Press 2 for geometry"
read choice
loop=2
if [ $choice = 1 ]; then
while [ $loop = 2 ]; do
echo -n "Enter X Value: "
read x
echo -n "Enter Operator: "
read op
echo -n "Enter Y Value: "
read y
ans=$((x $op y))
echo "$x $op $y = $ans"
echo "____________________"
echo "To input a new function, press enter"
read cont
done
fi

Looping(?) an if statement

I'm a noob to shell scripting and am wondering about this:
#!/usr/local/bin/bash
number=5
echo "Enter 'yes' to continue, 'no' to abort:"
read choice
if [ $choice = yes ]; then
while [ $number -lt 10 ]; do
echo "The script is now looping!"
done
elif [ $choice = no ]; then
echo "Loop aborted"
else
echo "Please say 'yes' or 'no'"
read choice
# What now?
fi
How would I go about the if statement rechecking your $choice (On line 13) if you do not specify "yes" or "no"?
Thank you.
You can put the code from "echo Enter..." till fi in an outer "while" loop. The while loop would loop until $choice is "yes" or "no". Remove the last "else" clause while doing this (it would be redundant).
P.S. you need to increment (or change) $number in your inner while loop. Otherwise, it will run infinitely.
You could keep track of whether to loop in a variable called invalid_choice
invalid_choice=true
while $invalid_choice; do
read choice
if [ "$choice" = "yes" ]; then
invalid_choice=false
...
elif [ "$choice" = "no" ]; then
invalid_choice=false
...
else
echo "Please say yes or no"
done
Or you could generalize it into a function if you need to do this a lot:
function confirm() {
local ACTION="$1"
read -p "$ACTION (y/n)? " -n 1 -r -t 10 REPLY
echo ""
case "$REPLY" in
y|Y ) return 0 ;;
* ) return 1 ;;
esac
}
confirm "Do something dangerous" || exit

Resources