在Bash中模拟do-while循环的最佳方法是什么?
我可以在进入while
循环之前检查条件,然后继续重新检查循环中的条件,但这是重复的代码。有更清洁的方式吗?
我的剧本的伪代码:
while [ current_time <= $cutoff ]; do
check_if_file_present
#do other stuff
done
如果在check_if_file_present
时间之后启动,则不会执行$cutoff
,并且会执行此操作。
答案 0 :(得分:178)
两个简单的解决方案:
在while循环之前执行一次代码
actions() {
check_if_file_present
# Do other stuff
}
actions #1st execution
while [ current_time <= $cutoff ]; do
actions # Loop execution
done
或者:
while : ; do
actions
[[ current_time <= $cutoff ]] || break
done
答案 1 :(得分:124)
在while
之后和测试之前放置循环体。 while
循环的实际主体应该是无操作。
while
check_if_file_present
#do other stuff
(( current_time <= cutoff ))
do
:
done
如果您发现更可读,则可以使用continue
而不是冒号。您还可以插入一个仅在迭代之间运行的命令(不是在第一次或之后),例如echo "Retrying in five seconds"; sleep 5
。或者在值之间打印分隔符:
i=1; while printf '%d' "$((i++))"; (( i <= 4)); do printf ','; done; printf '\n'
我将测试更改为使用双括号,因为您似乎在比较整数。在双方括号内,比较运算符如<=
是词法的,例如,在比较2和10时会给出错误的结果。那些操作符不能在单个方括号内工作。
答案 2 :(得分:6)
如果您发现更易读的
,则可以使用continue代替冒号
这种方法模仿了我正在寻找的Do-While循环的方式 - 在动作之后进行条件测试。我还发现我可以在do语句之后放置一个索引增量(如果需要),而不是一个continue语句。
while
check_if_file_present
#do other stuff
(( current_time <= cutoff ))
do
(( index++ ));
done
答案 3 :(得分:2)
此实现:
do=true
while $do || conditions; do
do=false
# your code ...
done
它也可以与读取循环配合使用,跳过第一次读取:
do=true
while $do || read foo; do
do=false
# your code ...
echo $foo
done
答案 4 :(得分:0)
我们可以使用while [[condition]]; do true; done
在Bash中模拟do-while循环:
while [[ current_time <= $cutoff ]]
check_if_file_present
#do other stuff
do true; done
例如。这是我在bash脚本中获取ssh connection的实现:
#!/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
它将按以下顺序给出输出:
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"