shell脚本中的while和do之间

shell脚本中的while和do之间

我有以下运行良好的脚本:

!/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 之前的最后一个命令,则dodo 接收到的退出代码始终为 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

相关内容