Siddharth
Siddharth

Reputation: 192

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

Upvotes: 1

Views: 301

Answers (3)

Darkman
Darkman

Reputation: 2981

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'

Upvotes: 0

Ivan
Ivan

Reputation: 7253

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++))
}

Upvotes: 1

tripleee
tripleee

Reputation: 189297

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.

Upvotes: 3

Related Questions