在 Bash 中模拟 do-while 循环
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16489809/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Emulating a do-while loop in Bash
提问by Alex
What is the best way to emulate a do-while loop in Bash?
在 Bash 中模拟 do-while 循环的最佳方法是什么?
I could check for the condition before entering the while
loop, and then continue re-checking the condition in the loop, but that's duplicated code. Is there a cleaner way?
我可以在进入while
循环之前检查条件,然后继续重新检查循环中的条件,但这是重复的代码。有更干净的方法吗?
Pseudo code of my script:
我的脚本的伪代码:
while [ current_time <= $cutoff ]; do
check_if_file_present
#do other stuff
done
This doesn't perform check_if_file_present
if launched after the $cutoff
time, and a do-while would.
check_if_file_present
如果在该$cutoff
时间之后启动,则不会执行此操作,而 do-while 会执行。
回答by jm666
Two simple solutions:
两个简单的解决方案:
Execute your code once before the while loop
actions() { check_if_file_present # Do other stuff } actions #1st execution while [ current_time <= $cutoff ]; do actions # Loop execution done
Or:
while : ; do actions [[ current_time <= $cutoff ]] || break done
在 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
回答by Paused until further notice.
Place the body of your loop after the while
and before the test. The actual body of the while
loop should be a no-op.
while
在测试之后和之前放置循环体。while
循环的实际主体应该是空操作。
while
check_if_file_present
#do other stuff
(( current_time <= cutoff ))
do
:
done
Instead of the colon, you can use continue
if you find that more readable. You can also insert a command that will only run betweeniterations (not before first or after last), such as echo "Retrying in five seconds"; sleep 5
. Or print delimiters between values:
continue
如果您发现冒号更具可读性,则可以使用它来代替冒号。您还可以插入一个仅在迭代之间运行的命令(不在第一个或最后一个之前),例如echo "Retrying in five seconds"; sleep 5
. 或打印值之间的分隔符:
i=1; while printf '%d' "$((i++))"; (( i <= 4)); do printf ','; done; printf '\n'
I changed the test to use double parentheses since you appear to be comparing integers. Inside double square brackets, comparison operators such as <=
are lexical and will give the wrong result when comparing 2 and 10, for example. Those operators don't work inside single square brackets.
我将测试更改为使用双括号,因为您似乎在比较整数。例如,在双方括号内,比较运算符<=
是词法的,并且在比较 2 和 10 时会给出错误的结果。这些运算符在单个方括号内不起作用。
回答by Chetabahana
We can emulate a do-while loop in Bash with while [[condition]]; do true; done
like this:
我们可以while [[condition]]; do true; done
像这样在 Bash 中模拟 do-while 循环:
while [[ current_time <= $cutoff ]]
check_if_file_present
#do other stuff
do true; done
For an example. Here is my implementation on getting ssh connectionin bash script:
举个例子。这是我在 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
It will give the output in sequence as below:
它将按顺序给出输出,如下所示:
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' ([email protected]: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"