Shell 脚本不会根据用户输入重新启动

Shell 脚本不会根据用户输入重新启动

我有这段代码,由于某种原因,它没有注意到输入为“是”以重新启动程序。它只是不断询问“您想再次订购吗”。似乎是什么问题(可能很简单),但我不知道。

#!/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/sh您可能不理解 POSIX shell 标准的一些扩展bash,但您也可能只是幸运。更改第一行以便bash使用它。

shell 脚本中的字符串比较可以使用

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

这比调用“更便宜”并且更容易阅读grep

您还可以使用case ... esac

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

重新执行脚本以再次执行是脆弱且非常不传统的。例如,如果脚本被调用为bash script.sh.最好引入一个循环,如果用户不想再尝试一次,则可以打破该循环。

bash还有一个select循环,您可以像这样使用:

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

另请注意,您可以简单地将字符串与 进行比较=

相关内容