사용자 입력에 따라 쉘 스크립트가 다시 시작되지 않습니다.

사용자 입력에 따라 쉘 스크립트가 다시 시작되지 않습니다.

이 코드가 있는데 어떤 이유로 프로그램을 다시 시작해도 입력이 "예"로 인식되지 않습니다. 계속 "다시 주문하시겠습니까?" 라고 물어보네요. 무엇이 문제인 것 같은데(아마도 간단한 것일 수도 있지만) 잘 모르겠습니다.

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

또한 대답이 "예" 또는 "아니오"가 아닌 경우 인식하고 정답을 나타내는 줄을 인쇄하도록 하려면 어떻게 해야 합니까?

답변1

스크립트의 주요 문제점은 order리터럴 문자열이 존재하는지 테스트한다는 것입니다 yes. 아마도 "$order".

또 다른 문제는 를 사용하여 이 스크립트(스크립트 bash) 를 실행한다는 것입니다 /bin/sh. /bin/shPOSIX 쉘 표준에 대한 일부 확장을 이해하지 못할 수도 있지만 bash운이 좋을 수도 있습니다. 이를 사용 하려면 첫 번째 줄을 변경하십시오 bash.

쉘 스크립트의 문자열 비교는 다음을 사용하여 수행할 수 있습니다.

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

이것은 "그리고 읽기 쉽다 grep"라고 부르는 것보다 저렴합니다.

다음을 사용할 수도 있습니다 case ... esac.

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

다시 실행하기 위해 스크립트를 다시 실행하는 것은 불안정하고 매우 색다른 작업입니다. 예를 들어 스크립트가 bash script.sh.

bashselect다음과 같이 사용할 수 있는 루프 도 있습니다 .

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

이를 통해 사용자 입력을 더 효과적으로 제어할 수 있습니다.


사용자의 대화형 입력을 읽고 종료할지 묻는 일반적인 접근 방식은 다음과 같습니다.

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

여기에 질문을 하고 일부 처리를 수행하는 외부 루프가 있습니다. 그런 다음 사용자에게 다시 갈 것인지 묻습니다. "아니요"( N또는 로 시작하는 모든 항목 n) 라고 대답하면 break루프를 종료합니다.

최종 테스트는 검증일 수도 있습니다 $data. 사용자가 처음에 잘못된 입력을 입력한 경우 read유효한 입력이 제공될 때까지 다시 요청해야 할 수도 있습니다.

이것(또는 당신이 읽은 내용)의 장점은 $data그것이 여전히 존재하고 입력 루프 이후에 사용 가능하므로 $data루프 내부가 아닌 나중에 처리할 수 있다는 것입니다.

의사코드:

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

main-code:
    use-validated-data

답변2

order다음 접두사를 붙여 $역참조하는 것을 잊었습니다 .

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

또한 간단히 문자열을 와 비교할 수도 있습니다 =.

관련 정보