3

I have this code and for some reason it doesn't notice the input being 'yes' to restart the program. It just keeps asking 'Would you like to order again'. What seems to be the issue (it's probably simple), but I have no idea.

#!/bin/sh

read -rp 'Fish or chicken? ' protein
read -rp 'Beans or rice? ' starch
read -rp 'Broccoli or asparagus? ' veggie
read -rp 'Beer or beer? ' drink

echo "You have ordered the $protein with a side of $starch and $veggie, and     to drink you will have $drink"

while true; do
read -rp 'Would you like to order again? ' order
if echo "order" | grep -iq 'yes'; then
    exec $0
elif echo "order" | grep -iq 'no'; then
    exit 0
fi
done

Also, how do I make it recognise whether the answer is NOT a yes or no, and it'll print out a line saying to mention the right answer.

  • For your last question, in the script that you have, just insert an echo before the last done. It would be executed when the user enters neither yes no no. – Kusalananda Apr 23 '18 at 19:05
3

The main issue with your script is that you test the literal string order for whether it's yes or not. You probably meant "$order".

Another issue is that you run this script, which is a bash script, using /bin/sh. /bin/sh may not understand some of the extensions that bash makes to the POSIX shell standard, but you may also just be lucky. Change the first line so that bash is used instead.

A string comparison in a shell script may be done using

if [ "$order" = "yes" ]; then ...; fi

This is "cheaper" and easier to read than calling grep.

You may also use case ... esac:

case "$order" in
    yes) ... ;;
    no)  ... ;;
esac

Re-executing the script to have another go is fragile and very unconventional. It will, for example, very likely not work if the script is invoked as bash script.sh. It is better to introduce a loop that you break out of if the user don't want to have another go.

bash also has a select loop, that you can use like this:

echo 'Please select protein from this menu:'
select protein in "beans" "lentils" "tofu" "cheese"; do
    if [ -z "$protein" ]; then
        echo 'Invalid choice' >&2
    else
        printf 'You picked %s as protein\n' "$protein"
        break
    fi
done

This allows you to have greater control over the user's input.


A general approach for reading interactive input from a user and then asking about quitting or not:

while true; do
    read -p 'Enter data: ' -r data
    # use "$data" here for something

    read -p 'Again? [Y/n] ' answer

    case "$answer" in
        [Nn]*) break ;;
    esac
done

Here, you have an outer loop that asks the questions and does some processing. Then it asks the user whether they want to go again. If they answer "No" (anything starting with N or n), we break out of the loop.

The test at the end might also be a validation of $data. If the user entered invalid input in the first read, you may want to ask again until valid input is given.

The benefit of this is that the $data (or whatever you read) is alive and available after the input loop, so instead of doing processing on $data inside the loop, you can do so later.

Pseudo code:

input-loop:
    read-data
    validate-data
    if-valid exit input-loop
    goto input-loop

main-code:
    use-validated-data
-1

You forgot to prepend order with $ to dereference it:

#!/bin/sh

echo $0

read -rp 'Fish or chicken? ' protein
read -rp 'Beans or rice? ' starch
read -rp 'Broccoli or asparagus? ' veggie
read -rp 'Beer or beer? ' drink

echo "You have ordered the $protein with a side of $starch and $veggie, and     to drink you will have $drink"

while true; do
    read -rp 'Would you like to order again? ' order
    if echo "$order" | grep -iq 'yes'; then
    exec $0
    elif echo "$order" | grep -iq 'no'; then
    exit 0
    fi
done

Also notice that you can simply compare strings with =.

  • Knew it was something simple. One thing I also forgot to mention is how do I add a way for it to recognise that is not a Yes or No and then print out a line saying 'Say either yes or no', etc. EDIT: Dw, simple else statement – Dillan Apr 23 '18 at 18:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.