Looping(?) an if statement - bash

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

Related

Terminate shell script after three invalid input

Restricting user from trying multiple invalid attempt in shell scripting. I wrote the below script but somehow it's not getting me desire output. I have shared the script and script output both. Kindly help. Here I wanted script to terminate if user tried more than 3 times.
While true
do
echo -n "Enter yes or no"
read opt
case $opt in
yes) break ;;
no) break ;;
*) echo "Invalid input"
while [[ $err -le 3 ]]
do
If [[ $err -le 3 ]]
then
echo "err: $err"
((err++))
break
else
echo "Max limit crossed"
exit 1
fi
done
;;
esac
done
This was a nice question and I had a lot of fun solving it. I have to mention that I'm new to shell programming.
n=0
until [ $n -ge 3 ]
do
read line
if [ "$line" = "XYZ" ]; then
echo "Accepted"
break
else
n=$[$n+1]
echo " trying " $n "times "
fi;
done
This article helped me a lot to solve it.
Try:
#!/bin/bash
ANSWER=
max=3
while true; do
echo "Enter yes or no:"
read -r ANSWER
[[ $ANSWER == "yes" || $ANSWER == "no" ]] && break
echo Invalid Input
ANSWER=
((--max))
[[ $max -le 0 ]] && { echo "Max limit crossed"; exit 1; }
done

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

shell script * operation gives too many arguments

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

Shell script that asks user to continue with a y/n

I have a shell script that I want to ask the user if they want to continue. If they type 'n' and press enter the script will exit.
If they press 'y' and enter it will continue to run. I have this at the top of my script but it continues regardless of what I type.
What am I doing wrong ?
goon=
while [ -z $goon ]
do
echo -n 'Do you want to continue? '
read goon
if [[ $goon = 'n' ]]
then
break
fi
goon=
done
Use an infinity loop and case/esac like this:
while true
do
read -r -p 'Do you want to continue? ' choice
case "$choice" in
n|N) break;;
y|Y) echo 'Do your stuff here';;
*) echo 'Response not valid';;
esac
done
The 'break' statement will exit you out of your while loop.
If you want to exit the script you want to use 'exit'.
That works perfectly well for me if I get rid of the doubled square brackets:
if [ $goon = 'n' ]
Rather than echo + read, just use read -p
read -p "Do you want to continue? " goon
Here's a working example (== instead of = for equality testing)
goon=
while [ -z $goon ]
do
echo -n 'Do you want to continue? '
read goon
if [[ $goon == 'n' ]]
then
break
fi
goon=
done
Strange thing, the original works ok for me too ...
I'm less than positive, but it looks as though your if statement will always evaluate to false.
Here's a resource on BASH coding that explains how to use conditionals in the way you are attempting to.
http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-6.html#ss6.4
I think you mean "exit" instead of "break", if you want the whole script to exit.
Also, you aren't actually checking for "y", so it loops forever even if they do say "y".
if [[ $goon = 'n' ]]
then
exit
fi
if [[ $goon = 'y' ]]
then
break
fi
Try below script
#!/bin/bash
pause ()
{
REPLY=X
while [ "$REPLY" == "X" ] || [ "$REPLY" != "n" ]
do
echo -e "\t\tPress 'n' to continue\t\t\tPress 'x' to quit"
read -n1 -s
case "$REPLY" in
"x") exit ;;
"X") echo "case sensitive!!" ;;
"n") clear ;;
"N") echo "case sensitive!!" ;;
* ) echo "Invalid Option" ;;
esac
done
}
pause
echo "Hi"
am sure this script will give you only two options to move around...

Resources