Optional commands in UNIX - linux

I'm trying to create a session in unix that will allow my to ask a simple question and then ask different questions varying on the answer.
For example if I were to ask
'Enter a choice (quit/order)'
if 'quit' is entered then program should close
if 'order' is entered then the program should continue asking further questions.
If you can help that would be great! Thanks!

#!/bin/bash
echo "Lots of choices.."
read -p "What is your choice? " choice
echo "Your choice was $choice"
if [ $choice == "quit" ]
then
echo "Exiting.."; exit 0
fi
if [ $choice == "order" ]
then
echo "Doing some other stuff.."
fi

This is where the shell's select command comes in handy. I'm going to assume you're using bash
PS3="Enter a choice: "
select answer in Quit Order; do
case $answer in
Quit) echo "Thanks for playing."; exit ;;
Order)
# select is like an infinite loop: you need to break out of it
break
;;
*) echo "Use the numbers to select your answer." ;;
esac
done
# carry on with the next question

Related

Yes or No in Bash Script

I have a set of 100 questions. My requirement is when a user enter "yes", then question 1 should appear. If not, directly it go to question 2. Like that it should go on till 100 questions. Any lead would be appreciated.
This is what I tried, but it is failing.
#!/bin/bash
echo "Execute question1 "
select result in Yes No
do
echo "How to see apache config file"
exit
done
echo "execute question2"
select result in Yes No Cancel
do
echo "Command for listing processes"
exit
done
Thanks in advance
Here is a way to do this with an array.
#!/bin/bash
questions=(
"How to see apache config file"
"Command for listing processes"
"My hovercraft is full of eels"
)
for((q=0; q<${#questions[#]}; q++)); do
echo "Execute question $q?"
select result in Yes No; do
case $result in
Yes)
echo "${questions[q]}";;
esac
break
done
done
Using select for this seems rather clumsy, though. Perhaps just replace it with
read -p "Execute question $q? " -r result
case $result in
[Yy]*) echo "${questions[q]}";;
esac
Having just a list of questions still seems weird. With Bash 5+ you could have an associative array, or you could have a parallel array with the same indices with answers to the questions. But keeping each question and answer pair together in the source would make the most sense. Maybe loop over questions and answers and assign every other one to an answers array, and only increment the index when you have read a pair?
pairs=(
"How to see Apache config file"
"cat /etc/httpd.conf"
"Command for listing processes"
"ps"
"My hovercraft is full of what?"
"eels"
)
questions=()
answers=()
for((i=0; i<=${#pairs[#]}/2; ++i)); do
questions+=("${pairs[i*2]}")
answers+=("${pairs[1+i*2]}")
done
This ends up with two copies of everything, so if you are really strapped for memory, maybe refactor to just a for loop over the strings and get rid of the pairs array which is only useful during initialization.
Use an array of questions and loop over it, like this:
#!/bin/bash
n=1
questions=(
'How to see apache config file'
'Command for listing processes'
)
check_user_input(){
read -p "y/n " input
case $input in
[Yy]*) return 0;;
[Nn]*) return 1;;
*) check_user_input;;
esac
}
for question in "${questions[#]}"; {
echo "Execute question $n"
check_user_input && echo "$question"
((n++))
}
Here is a straight forward example. Play with it.
#!/bin/bash
echo "Type 'y' for yes, 'n' to skip or 'q' to quit and press Enter!"
for((i=1; i < 101; ++i)); do
echo 'Execute question '$i
while read user_input; do
if [[ "$user_input" = 'q' ]]; then
break 2
elif [[ "$user_input" = 'n' ]]; then
break
elif [[ $i -eq 1 ]]; then
echo 'How to see apache config file?'
break 2 # Change from "break 2" to "break" for the next question.
elif [[ $i -eq 2 ]]; then
echo 'Command for listing processes.'
break 2 # Change from "break 2" to "break" for the next question.
else
echo "Wrong input: $user_input"
echo "Type 'y' for yes, 'n' to skip or 'q' to quit and press Enter!"
fi
done
done
echo 'Finished'

How to Properly Set Up If in While Loop

I'm going to add the rest of the functionality to the program later it's still in it's early stages, but I cant seem to get out of the while loop for some reason even though the if statement is within it and under the menu. Here's the code so far.
continue="true"
#while loop to keep the code running till the user inputs Q
while [ $continue = "true" ]
#loop start
do
#clearing screen before showing the menu
clear
echo "A to Create a user account"
echo "B to Delete a user account"
echo "C to Change Supplementary Group for a user account"
echo "D to Create a user account"
echo "E to Delete a user account"
echo "F to Change Supplementary Group for a user account"
echo "Q to Quit"
read -p "What would you like to do?:" choice
#Test to end the program
if [ $choice = 'Q' ] || [ $choice = 'q']
then
$continue="false"
fi
#loop end
done```
As pointed out by Gordon, you need continue="false" not $continue="false".
Also, I advise using if [ "$choice" = 'Q' ] || [ "$choice" = 'q' ] so your script won't break if the user hits CR and did not enter anything. (Also note that you need a space before last ] in that statement.)
Although the syntax error has already been highlighted in the comments, I would suggest avoiding the continue variable entirely by using break. And you can also combine the two checks using a regex. Something like this
while true; do
read -p "What would you like to do?: " choice
if [[ "$choice" =~ [Q|q] ]]; then
break
fi
done
Though when I look at the echo statements in your question it seems like you would probably be better off avoiding the if entirely, and instead use a case statement
while true; do
read -p "What would you like to do?: " choice
case "$choice" in
q|Q) break
;;
a|A) echo "Creating a user account"
;;
#This catches anything else
*) echo "unknown option"
;;
esac
done

do-while loop using user input in shell scritping [duplicate]

This question already has answers here:
Why should there be spaces around '[' and ']' in Bash?
(5 answers)
Closed 2 years ago.
I am a beginner in bash scripting. and i look for similar questions but none gave me the results am looking for.
I want to create a shell that keep giving the user some options to choose from while the choice is not exit
Here is my code
choice=0
while [$choice!=4]
do
echo "please choose the operation you want!"
echo "1) Delete Data"
echo "2) Insert Data"
echo "3) Get Number of customers"
echo "4) Exit"
choice=$1
if [$choice=1]; then
echo "you have chosen to Delete Data"
elif [$choice=2]; then
echo "you have chosen to Insert Data"
elif [$choice=3]; then
echo "you have chosen to Get number of customers"
fi # EOF if
done
As you can see that i want my code to keep asking for the user options until the answer is not exit.
My Question is this code gives me an infinite loop.
Bash, ksh or zsh provides you with the select command that is exactly designed to present numbered options menu:
To get the usage of the select command, type help select in your bash terminal.
select: select NAME [in WORDS … ;] do COMMANDS; done
Select words from a list and execute commands.
The WORDS are expanded, generating a list of words. The set of expanded words is printed on the standard error, each preceded by a number. If in WORDS is not present, in "$#" is assumed. The PS3 prompt is then displayed and a line read from the standard input. If the line consists of the number corresponding to one of the displayed words, then NAME is set to that word. If the line is empty, WORDS and the prompt are redisplayed. If EOF is read, the command completes. Any other value read causes NAME to be set to null. The line read is saved in the variable REPLY. COMMANDS are executed after each selection until a break command is executed.
Exit Status:
Returns the status of the last command executed.
Here is an implementation of it with your selection menu:
#!/usr/bin/env bash
choices=('Delete Data' 'Insert Data' 'Get Number of customers' 'Exit')
PS3='Please choose the operation you want: '
select answer in "${choices[#]}"; do
case "$answer" in
"${choices[0]}")
echo 'You have chosen to Delete Data.'
;;
"${choices[1]}")
echo 'You have chosen to Insert Data.'
;;
"${choices[2]}")
echo 'You have chosen to Get number of customers.'
;;
"${choices[3]}")
echo 'You have chosen to Exit.'
break
;;
*)
printf 'Your answer %q is not a valid option!\n' "$REPLY"
;;
esac
done
unset PS3
Another implementation of the select command, using arguments rather than an array of choices:
#!/usr/bin/env ksh
PS3='Please choose the operation you want: '
set -- 'Delete Data' 'Insert Data' 'Get Number of customers' 'Exit'
select answer; do
case "$answer" in
"$1")
echo 'You have chosen to Delete Data.'
;;
"$2")
echo 'You have chosen to Insert Data.'
;;
"$3")
echo 'You have chosen to Get number of customers.'
;;
"$4")
echo 'You have chosen to Exit.'
break
;;
*)
printf 'Your answer %q is not a valid option!\n' "$REPLY"
;;
esac
done
If you want to use while loop with conditional 'case' syntax, try this:
while true
do
echo "1) Delete Data"
echo "2) Insert Data"
echo "3) Get Number of customers"
echo "4) Exit"
echo -ne "Enter your choice [0-4] > \c"
read choice
case "$choice" in
1) echo "you have chosen to Delete Data" ; break
;;
2) echo "you have chosen to Insert Data"; break
;;
3) echo "you have chosen to Get number of customers"; break
;;
4) exit
;;
*) clear
;;
esac
done
i found the error. it was statement typing issue not in the algorithm
my new code is
while [ "$(read choice)"!="4" ]
do
if [ "$choice"="1" ]; then
echo "you have chosen to Delete Data"
elif [ "$choice"="2" ]; then
echo "you have chosen to Insert Data"
elif [ "$choice"="3" ]; then
echo "you have chosen to Get number of customers"
fi # EOF if
echo "please choose the operation you want!"
echo "1) Delete Data"
echo "2) Insert Data"
echo "3) Get Number of customers"
echo "4) Exit"
done

How to create a normal running program? Because my program is run eternaly and wont stop

My English is very bad, but i'm try to explain my problem.
I want to create a small program on bash in which the user will have to guess the numbers. But my program has no end.
I'm novice on bash scripting, but i try to get better everyday.
I'm using CentOS 7. I go to /usr/bin/local and create some file, give him chmod +x and open with gedit:
#!/usr/bin/bash
#This script should ask us our name and play the game "Guess the Number" with us.
echo "What is your name?"
read name
echo "Hello $name"
echo "I want to play $ name with you, you have to guess the number from 1 to 10)"
echo "Are you ready?"
read rdy
answer=$(( answer = $RANDOM % 10 ))
read -p "Enter your number: " variant
while [ $answer != $variant ]; do
if [ $answer -gt $variant ]; then
echo "Your number is bigger, try again"
elif [ $answer -lt $variant ]; then
echo "Your number is smaller, try again"
continue
fi
done
eternal "Your number is smaller/bigger"
until you press ctrl+c
What I need to do, please help. I know non amateurs don't likes novices but i need your help, show me my mistake, and i can get better. Thanks!
#!/bin/bash
echo "What is your name?"
read name
echo "Hello $name"
echo "I want to play with you, you have to guess the number from 1 to 10"
answer=$(( $RANDOM % 10 ))
while true
do
read -p "Enter your number: " variant
if [ "$answer" -gt "$variant" ]; then
echo "The number is bigger, try again"
elif [ "$answer" -lt "$variant" ]; then
echo "The number is smaller, try again"
else
break;
fi
done
echo "Yes, the answer was ${answer}"
You call
read -p "Enter your number: " variant
before the while loop.
Inside the loop you never change the variant, so the original value is re-used in the while condition. For Eternity.
You can start with variant=-1 and move the readinside the loop or do something like #xiawi.

Bash if string = this or that [duplicate]

This question already has answers here:
How do I prompt for Yes/No/Cancel input in a Linux shell script?
(37 answers)
Closed 2 years ago.
Trying to write a script which will read what a user has imput... I know it's basic but im stuck on the first if..
echo "Please enter yes or no (y/n)?"
read string
if [ $string = "y" -o "n" ]
then
echo "User selected $string"
else
echo "You didn't enter y/n !!!"
fi
I would like it to be if [ $backup = "y" or "n" ]
Any ideas?
Use this syntax in bash :
if [ "a string" = "another one" ] ; then
# Whatever
fi
For multiple conditional statements such as OR, use:
if [ "a string" = "another one" ] || [ "$foo" = "bar" ] ; then
# Whatever
fi
bash also supports the non-standard [[ ... ]] expression, which can process a compound comparison using a single command, rather than 2 [ commands:
if [[ "a string" = "another one" || $foo = "bar" ]]; then
# Whatever
fi
Not the question you actually asked, but... You told the user to enter "yes" or "no" but only test for y or n - sure, you gave them a hint but users are hint-resistant. So maybe a looser test is in order:
echo "Please enter yes or no (y/n)"
read string
case "$string" in
[yY]* | [nN]*) echo "User entered $string" ;;
*) echo "I don't understand '$string'" ;;
esac
That will recognize any variation that begins with Y or N - usually that's good enough, but you could tighten up the tests. Also, since you'll probably want to do something different with a yes or no response you can expand the case (I've also tightened the tests in this one):
case "$string" in
[yY] | [yY][eE][sS]) echo "Here's where you process yes" ;;
[nN] | [nN][oO]) echo "And here you deal with no" ;;
*) echo "I don't understand '$string'" ;;
esac
You could do this with if statements but I find case more readable when more than two alternatives are possible and the test is appropriate to case syntax.
You can also try:
echo "Please enter yes or no (y/n)?"
read string
if [[ "$string" =~ ^(y|n)$ ]]
then
echo "User selected $string"
else
echo "You didn't enter y/n !!!"
fi
I nice solution is would be with case, which is easier to extend if you want to make your input more complex
case $string in
y|n) echo "User selected $string"
;;
*) echo "You didn't enter y/n !!!"
;;
esac
From there you can easily modify it to accept Uppercase or whatever:
case $string in
y|Y) echo "yes, Sir!"
;;
n|N) echo "No, can't do"
;;
*) echo "Say what?"
;;
esac
Check case statements for more info.

Resources