在Bash中模拟do-while循环

Ale*_*lex 123 bash loops do-while

在Bash中模拟do-while循环的最佳方法是什么?

我可以在进入while循环之前检查条件,然后继续重新检查循环中的条件,但这是重复的代码.有更干净的方式吗?

我的脚本的伪代码:

while [ current_time <= $cutoff ]; do
    check_if_file_present
    #do other stuff
done
Run Code Online (Sandbox Code Playgroud)

check_if_file_present如果在$cutoff时间之后启动,这将不会执行,并且会执行.

jm6*_*666 200

两个简单的解决方

  1. 在while循环之前执行一次代码

    actions() {
       check_if_file_present
       # Do other stuff
    }
    
    actions #1st execution
    while [ current_time <= $cutoff ]; do
       actions # Loop execution
    done
    
    Run Code Online (Sandbox Code Playgroud)
  2. 要么:

    while : ; do
        actions
        [[ current_time <= $cutoff ]] || break
    done
    
    Run Code Online (Sandbox Code Playgroud)

  • bash 中的“type true”(一直回到 bash 3.2)返回“true is a shellbuiltin”。确实,“/bin/true”是一个程序;true 的不正确之处在于 `true` 不是内置的。(tl;dr: true 是 bash 内置程序和程序) (11认同)
  • 注意复制粘贴:[这个其他答案](/sf/answers/1154403491/)是这样做的更规范的方式. (7认同)
  • `:`是内置的,相当于内置的`true`.他们都"无所作为". (6认同)
  • @loxaxs,哦`逗号`...这样的细节,但在句子中似乎很关键:“什么也不做,成功”。 (4认同)
  • @loxaxs 这在 zsh 等中是正确的,但在 Bash 中则不然。`true` 是一个实际的程序,而 `:` 是内置的。前者只是以“0”退出(“false”以“1”退出),后者绝对不执行任何操作。您可以使用“哪个是正确的”来检查。 (2认同)
  • 从来没有说过任何不同的话,只是“true”不是 Bash 中内置的。它是通常在“/bin”中找到的程序。 (2认同)

Pau*_*ce. 140

while在测试之前和之后放置环体.while循环的实际主体应该是无操作.

while 
    check_if_file_present
    #do other stuff
    (( current_time <= cutoff ))
do
    :
done
Run Code Online (Sandbox Code Playgroud)

continue如果您发现更可读,则可以使用冒号而不是冒号.您还可以插入仅迭代之间(不是在第一次之前或之后)之间运行的命令,例如echo "Retrying in five seconds"; sleep 5.

我将测试更改为使用双括号,因为您似乎在比较整数.例如,在双方括号内,比较运算符<=是词法,并且在比较2和10时会给出错误的结果.那些操作符不能在单个方括号内工作.

  • 这是一个美味的技巧,直接进入我的特殊包. (21认同)
  • 这是最好的答案! (3认同)
  • 它是否相当于单行`while { check_if_file_present; ((当前时间&lt;=截止时间)); }; 做 :; 完成了`? 即“while”条件内的命令是否有效地用分号而不是“&amp;&amp;”分隔,并由“{}”分组? (2认同)
  • @ruslan:不,这是最后的回报值.`假的; 假; 假; 真正; 在这里回声; 打破; 完成`输出"这里" (2认同)

KJ7*_*LNW 9

这个实现:

  • 没有代码重复
  • 不需要额外的功能()
  • 不依赖于循环“while”部分中代码的返回值:
do=true
while $do || conditions; do
  do=false
  # your code ...
done
Run Code Online (Sandbox Code Playgroud)

它也适用于读取循环,跳过第一次读取:

do=true
while $do || read foo; do
  do=false

  # your code ...
  echo $foo
done
Run Code Online (Sandbox Code Playgroud)


小智 7

如果您发现更可读,则可以使用continue,而不是冒号

这种方法模仿了我正在寻找的Do-While循环的方式 - 在动作之后进行条件测试.我还发现我可以在do语句之后放置索引增量(如果需要),而不是continue语句.

while 
    check_if_file_present
    #do other stuff
    (( current_time <= cutoff ))
do
    (( index++ ));
done
Run Code Online (Sandbox Code Playgroud)


Che*_*ana 5

我们可以while [[condition]]; do true; done像这样在 Bash 中模拟 do-while 循环:

while [[ current_time <= $cutoff ]]
    check_if_file_present
    #do other stuff
do true; done
Run Code Online (Sandbox Code Playgroud)

举个例子。这是我在 bash 脚本中获取ssh 连接的实现:

#!/bin/bash
while [[ $STATUS != 0 ]]
    ssh-add -l &>/dev/null; STATUS="$?"
    if [[ $STATUS == 127 ]]; then echo "ssh not instaled" && exit 0;
    elif [[ $STATUS == 2 ]]; then echo "running ssh-agent.." && eval `ssh-agent` > /dev/null;
    elif [[ $STATUS == 1 ]]; then echo "get session identity.." && expect $HOME/agent &> /dev/null;
    else ssh-add -l && git submodule update --init --recursive --remote --merge && return 0; fi
do true; done
Run Code Online (Sandbox Code Playgroud)

它将按顺序给出输出,如下所示:

Step #0 - "gcloud": intalling expect..
Step #0 - "gcloud": running ssh-agent..
Step #0 - "gcloud": get session identity..
Step #0 - "gcloud": 4096 SHA256:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX /builder/home/.ssh/id_rsa (RSA)
Step #0 - "gcloud": Submodule '.google/cloud/compute/home/chetabahana/.docker/compose' (git@github.com:chetabahana/compose) registered for path '.google/cloud/compute/home/chetabahana/.docker/compose'
Step #0 - "gcloud": Cloning into '/workspace/.io/.google/cloud/compute/home/chetabahana/.docker/compose'...
Step #0 - "gcloud": Warning: Permanently added the RSA host key for IP address 'XXX.XX.XXX.XXX' to the list of known hosts.
Step #0 - "gcloud": Submodule path '.google/cloud/compute/home/chetabahana/.docker/compose': checked out '24a28a7a306a671bbc430aa27b83c09cc5f1c62d'
Finished Step #0 - "gcloud"
Run Code Online (Sandbox Code Playgroud)