I would like to write a simple bash script for training multiple choice tests. Ask one question; give four choices (a, b, c, d); if user enters input, show if it is wrong or right and continue with the next question.
Here is my code so far:
#!/usr/bin/bash
echo Question1="How much is 2+2?"
echo a="1"
echo b="2"
echo c="3"
echo d="4"
read Question1
if [ "$Question1" = "d" ];
then
echo "this is correct"
else
echo "this is NOT correct"
fi
All samples about the read command example I found so far on youtube etc. stop after one question. How can I ask multiple questions? Entering another question does not work and bash shows a syntax error:
#!/usr/bin/bash
echo Question1="How much is 2+2?"
echo a="1"
echo b="2"
echo c="3"
echo d="4"
read Question1
if [ "$Question1" = "d" ];
then
echo "this is correct"
else
echo "this is NOT correct"
echo Question2="How much is 2+1?"
echo a="1"
echo b="2"
echo c="3"
echo d="4"
read Question2
if [ "$Question2" = "c" ];
then
echo "this is correct"
else
echo "this is NOT correct"
fi
It is giving you a syntax error because you don't have a fi after your first if statement, probably an error during copy/pasting.
Afterwards it should work fine.
This is where the select command is handy
PS3="How much is 2+2? "
select choice in 1 2 3 4; do
if [[ $choice == 4 ]]; then
echo "Correct"
break
fi
echo "Incorrect"
done
PS3="How much is 2+1? "
select choice in 1 2 3 4; do
if [[ $choice == 3 ]]; then
echo "Correct"
break
fi
echo "Incorrect"
done
Or, we can encapsulate the repetition in a function:
question() {
local PS3="$1 " answer=$2 choice
shift 2
select choice in "$#"; do
if [[ $choice == "$answer" ]]; then
echo "Correct"
break
fi
echo "Incorrect"
done
}
question "How much is 2+2?" 4 1 2 3 4
question "How much is 2+1?" 3 1 2 3 4
Related
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
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
I have a config.txt file where the first line has a number 1, I need to read this and do certain tasks based on whether the number is 1 or 2 or 3 etc
The problem is I cannot test that config value, none of the if statements below work, and I tried many more variances.
config=$(head -n 1 /mnt/writable/config.txt) #grabs vale from file
echo $config #prints 1
But the following if statements do not echo anything.
if [[ "$config" = "1" ]];
then
echo "is a 1";
fi
if [[ "$config" == "1" ]];
then
echo "is a 1";
fi
if [[ "$config" = 1 ]];
then
echo "is a 1";
fi
if [ $config = 1 ];
then
echo "is a 1";
fi
I also tried "declare -i config" at the top but that didnt work either. Spent a day and no luck so far.
Because you have space or tab in your first line( I think )
So if you print using
echo $config
it will print 1 correctly but when you use it in if condition, it may not work as your wish ...
so I suggest that you should try following in your script,
config=$(head -n 1 /mnt/writable/config.txt | tr -d '[:space:]')
and all your if condition may work.
Integer equality can be tested by using -eq option.
Do man test for further details about if condition.
if [ $config -eq 1 ]; then echo "config is 1"; else echo "config is not 1"; fi
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
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
If statement is not following its conditional
I believe it to be something that be wrong with my bc or my variables, but I could be wrong.
This is a bit of my code.
#!/bin/bash
#this is a game that is two player and it is a race to get to
#100 before the other player
echo "Player 1 name?"
read p1
echo "Player 2 name?"
read p2
echo "Okay $p1 and $p2. $p1 will go first"
p1s=0
p2s=0
pt=1
while [ $pt -eq 1 ]; do
echo "roll or stay"
read choice
if [ $choice ="r" ]; then
die=$(($RANDOM%6+1))
if [ $choice ="s" ]; then
echo "Okay $p1 your score is $p1s"
echo "$p2 turn now"
sleep 1
count=0
pt=2
else
pt=1
fi
fi
if [ $die -eq 1 ]; then
p1s=$(echo "$p1s-$count" |bc)
echo "You rolled a 1. Your score is $p1s"
echo "$p2 turn now."
sleep 1
count=0
pt=2
elif [ $die -gt 1 ]; then
p1s=$(echo "$p1s+$die" |bc)
count=$(echo "$count+$die" |bc)
echo "You rolled a $die. Your score is $p1s"
pt=1
fi
if [ $p1s -gt 99 ]; then
echo "$p1 won. $p2 lost"
echo "would you like to play again?"
read again
else
if [ $again ="yes" ]; then
echo "Okay one second."
sleep 1
clear
bash num.sh
else
if [ $again = "no" ]; then
exit
else
echo "I guess no then?"
exit
fi
fi
fi
done
What happens is this
Player 1 name?
1
Player 2 name?
2
Okay 1 and 2. 1 will go first
roll or stay
r
num.sh: line 24: [: r: unary operator expected
num.sh: line 42: [: -eq: unary operator expected
num.sh: line 51: [: -gt: unary operator expected
Okay one second.
Player 1 name?
Here it finds bunch of errors and such. Then starts over.
Thank you in advance.
I guess conditional to check choice variable has wrong syntax, it should be written as:
if [ "$choice" -eq "r" ]; then
...
or with enhanced brackets
if [[ "$choice" == "r" ]]; then
...