如何在shell脚本的循环中设置父变量?

问题描述 投票:0回答:1

我最近在大学才开始编写 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

我在网上查了一下,但找不到任何答案。我知道这很简单,但我是新人。

任何帮助,无论是代码还是整个结构,我们将不胜感激。

谢谢。

bash shell variables global-variables until-loop
1个回答
0
投票

正如其他人提到的,您的代码中没有子 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

我所做的改变是:

  1. 使用的局部变量
  2. 使用算术运算符
    ((...))
    进行数字比较
  3. 一如既往地在
    IFS=
    上使用
    -r
    read
    ,除非您有特定需要删除其中任何一个,请参阅 why-is-using-a-shell-loop-to-process-text -被认为是不好的做法
  4. 一如既往地引用变量,除非您有特定的需要删除它们,请参阅https://mywiki.wooledge.org/Quotes
  5. 摆脱了
    loopSwitch
    ,因为它的含义与
    playAgain
    几乎完全相同,然后将
    playAgain
    重命名为
    keepPlaying
    ,因此对于第一次循环迭代来说也更有意义。
  6. 定义一个变量来保存目标数字
    6
    ,而不是在比较中对其进行硬编码,以便将来维护/增强(例如,如果您想添加打印语句来转储它)。
  7. keepPlaying
    进行了独立于大小写的测试,并默认保留其先前的值,以便用户只需按 ENter,而不是在每次迭代时键入“y”。
  8. 使用了更常见的缩进样式。
© www.soinside.com 2019 - 2024. All rights reserved.