我有以下运行良好的脚本:
!/bin/bash
a=12
while [ $a -gt 10 ]
do
echo "$a"
a=$(($a-1))
done
echo "done"
如果我在“do”上方添加“echo Something”行,我预计会在该行中看到语法错误。似乎[ $a -gt 10 ]
被绕过了,它变成了无限循环。怎么会发生这种事?
答案1
从bash 手册:
while
该命令的语法
while
是:尽管测试命令;做后续命令; 完毕consequent-commands
只要test-commands
退出状态为零就执行。返回状态是 中执行的最后一个命令的退出状态consequent-commands
,如果没有执行则为零。
笔记:test-commands
,复数。您可以在测试中使用多个命令,因此这是一个完全有效的循环,以命令列表[ $a -gt 10 ]; echo "$a"
作为测试:
while [ $a -gt 10 ]
echo "$a"
do
a=$(($a-1))
done
虽然该命令[ $a -gt 10 ]
可能会失败,也可能不会失败,但echo
它(几乎)总是会成功(除非它无法写入文本,或者发生了其他错误),所以最终的测试命令的退出状态将始终为成功,并且循环将始终运行。
答案2
从man bash
:
而列表-1;做列表2; did
while 命令会持续执行列表list-2
,只要最后一个命令列表中list-1
返回退出状态为零。
这意味着 alist
可以包含多个命令,它确实如此(主要由分号或换行符分隔)。
所以,这非常有效:
#!/bin/bash
a=12
while
echo something
echo "a before test = $a"
[ a -gt 10 ]
do
echo "a after test = $a"
a=$(($a-1))
done
echo "done"
如果 is echo 之前的最后一个命令,则do
do 接收到的退出代码始终为 true (0),并且循环将变为无限。
答案3
这里的其他答案暗示但没有明确说明的是,这[
是一个内置的命令,不是语句的语法部分while
。
尝试help [
在命令行中输入:
[
:[
arg...]
评估条件表达式。这是“test”内置函数的同义词,但最后一个参数必须
是文字]
,以匹配开头[
。
所以你的脚本是确切地作为:
!/bin/bash
a=12
while test $a -gt 10
do
echo "$a"
a=$(($a-1))
done
echo "done"
您更改为:
!/bin/bash
a=12
while test $a -gt 10; echo something
do
echo "$a"
a=$(($a-1))
done
echo "done"
答案4
(作为补充其他答案的注释)。
在条件列表中使用多个命令通常用于实现类似于 C 的循环do { blah; blah; } while (condition)
,即在循环末尾检查条件,以便循环中的代码至少运行一次。
在 中sh
,您可以这样做:
while
blah
blah
condition
do
continue # or :
done
尽管其他方法也是可能的,例如:
while true; do
blah
blah
condition || break
done
或者:
continue=true
while "$continue"; do
blah
blah
condition || continue=false
done
end=false
until "$end"; do
blah
blah
condition || end=true
done