我最近在大学才开始编写 bash 脚本。
我一直在尝试学习循环,我有以下几点:
Guessing_Game() {
echo "Guessing Game!"
set loopSwitch = 0
until [[ $loopSwitch == 1 ]];
echo $loopSwitch
do
read -p "Guess a number between 1 and 10: " userGuess
if [[ $userGuess == 6 ]];
then
echo "Well done! You win."
else
echo "Incorrect guess."
fi
read -p "Would you like to play again? (y/n)" playAgain
if [[ $playAgain == "n" ]];
then
set loopSwitch = 1
fi
done
}
据我所知,由于loopSwitch变量是在子shell之外设置的,所以它只能更改该子shell内的值?
如何设置 LoopSwitch 变量以便退出循环?
我尝试通过代码的几个部分回显变量 $loopSwitch - 就在进入直到循环之后,在最后一个 if 语句内 - 并且没有任何输出,所以我认为它不存在于直到循环?
为了
set loopSwitch = 1
部分,我试过了:
set loopSwitch = 1
set $loopSwitch = 1
loopSwitch = 1
$loopSwitch = 1
我在网上查了一下,但找不到任何答案。我知道这很简单,但我是新人。
任何帮助,无论是代码还是整个结构,我们将不胜感激。
谢谢。
正如其他人提到的,您的代码中没有子 shell。我想你可能看到过这样的代码
num=27; seq 3 | while IFS= read -r line; do num="$line"; echo "inside: $num"; done; echo "outside: $num"
它会输出 1, 2, 3, 27 并误解了为什么最后输出 27 而不是 3。这并不是因为循环在子 shell 中运行,而是因为管道 (|) 两侧的命令在子 shell 中运行。这就是为什么你要使用命令替换 (
<(command)
) 来编写
num=27; while IFS= read -r line; do num="$line"; echo "inside: $num"; done < <(seq 3); echo "outside: $num"
它将输出 1, 2, 3, 3。请参阅 mywiki.wooledge.org/BashFAQ/024。
关于你问题中的代码,FWIW我会把它写成:
$ cat tst.sh
#!/usr/bin/env bash
Guessing_Game() {
local keepPlaying='y' theNumber=6
echo 'Guessing Game!'
until [[ "$keepPlaying" =~ [nN] ]]; do
echo "$keepPlaying"
IFS= read -r -p 'Guess a number between 1 and 10: ' userGuess
if (( userGuess == theNumber )); then
echo "Well done! You win."
else
echo "Incorrect guess."
fi
IFS= read -r -p 'Would you like to play again? ([y]/n)' keepPlaying
done
}
Guessing_Game
我所做的改变是:
((...))
进行数字比较IFS=
上使用 -r
和 read
,除非您有特定需要删除其中任何一个,请参阅 why-is-using-a-shell-loop-to-process-text -被认为是不好的做法。loopSwitch
,因为它的含义与 playAgain
几乎完全相同,然后将 playAgain
重命名为 keepPlaying
,因此对于第一次循环迭代来说也更有意义。6
,而不是在比较中对其进行硬编码,以便将来维护/增强(例如,如果您想添加打印语句来转储它)。keepPlaying
进行了独立于大小写的测试,并默认保留其先前的值,以便用户只需按 ENter,而不是在每次迭代时键入“y”。