O Shell Script não será reiniciado com a entrada do usuário

3

Eu tenho este código e, por algum motivo, ele não percebe a entrada sendo 'sim' para reiniciar o programa. Apenas fica perguntando "Gostaria de pedir novamente?". O que parece ser o problema (provavelmente é simples), mas não faço ideia.

#!/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

Além disso, como faço para reconhecer se a resposta NÃO é um sim ou não e imprimo uma linha dizendo para mencionar a resposta certa.

    
por Dillan 23.04.2018 / 20:23

2 respostas

3

O principal problema com o seu script é que você testa a string literal order para saber se é yes ou não. Você provavelmente quis dizer "$order" .

Outro problema é que você executa esse script, que é um script bash , usando /bin/sh . /bin/sh pode não entender algumas das extensões que bash faz para o padrão de shell POSIX, mas você também pode ter sorte. Altere a primeira linha para que bash seja usado.

Uma comparação de string em um script de shell pode ser feita usando

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

Isto é "mais barato" e mais fácil de ler do que chamar grep .

Você também pode usar case ... esac :

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

Re-executar o script para ter outra chance é frágil e muito pouco convencional. Será, por exemplo, muito provável que não funcione se o script for invocado como bash script.sh . É melhor introduzir um loop que você interrompa se o usuário não quiser fazer outra.

bash também tem um select loop, que você pode usar assim:

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

Isso permite que você tenha maior controle sobre a entrada do usuário.

Uma abordagem geral para ler a entrada interativa de um usuário e, em seguida, perguntar sobre como sair ou não:

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

Aqui, você tem um loop externo que faz as perguntas e faz algum processamento. Em seguida, ele pergunta ao usuário se deseja ir novamente. Se eles responderem "Não" (qualquer coisa que comece com N ou n ), nós break sairemos do loop.

O teste no final também pode ser uma validação de $data . Se o usuário inseriu uma entrada inválida no primeiro read , você pode querer perguntar novamente até que seja dada uma entrada válida.

O benefício disso é que $data (ou o que você lê) está ativo e disponível após o loop de entrada, então, em vez de fazer processamento em $data dentro do loop, você pode fazer isso mais tarde. >

pseudocódigo:

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

main-code:
    use-validated-data
    
por 23.04.2018 / 20:37
-1

Você se esqueceu de prefixar order com $ para cancelar a referência:

#!/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

Note também que você pode simplesmente comparar strings com = .

    
por 23.04.2018 / 20:34