我想循环执行命令,直到它以退出代码退出0
,所以我尝试了:
$ while/until $?; do $command; done
但until/while
似乎只接受布尔值 liketrue/false
和 not 0/1
。
我是否错过了类似的东西[[ ]]
或其他东西?
答案1
和while
关键字until
需要一个命令作为他们的论点。如果命令返回零退出状态,表示“成功”,while
将运行循环体中的命令,until
而不是运行循环体中的命令。
您的代码似乎使用while
and until
with $?
(最近命令的退出状态)作为命令。除非系统上有以整数作为名称的命令,否则这将不起作用。什么会工作是使用test
命令将其与 进行比较0
,例如,与
until test "$?" -eq 0; do some-command; done
或者,使用缩写形式test
,
until [ "$?" -eq 0 ]; do some-command; done
现在的问题显然是$?
进入循环时很可能为零,从而阻止循环运行一次。让命令本身直接将其退出状态提供给while
or会更有意义until
(除非您想通过在循环之前$?
调用eg 来初始化为非零值,这看起来很奇怪)。false
使用标准 POSIX(虽然不是 Bourne,但现在这并不重要)shell 语法:
while ! some-command; do continue; done
或(Bourne 和 POSIX),
until some-command; do continue; done
这两个命令都会运行,some-command
直到返回零退出状态(“成功”)。在每次迭代中,它都会执行continue
循环体内的关键字。执行continue
会立即跳到循环的下一次迭代,但您可以将其替换为 egsleep 5
以便在每次迭代中都有短暂的延迟,或者使用:
which 不执行任何操作。
另一种变体是有一个无穷命令成功时退出的循环:
while true; do some-command && break; done
或者,稍微冗长一点,并添加空气以提高可读性,
while true; do
if some-command; then
break
fi
done
唯一一次你真正需要使用$?
是当您需要跟踪该值一段时间时,如
somefunction () {
grep -q 'pattern' file
ret=$?
if [ "$ret" -ne 0 ]; then
printf 'grep failed with exit code %s\n' "$ret"
fi >&2
return "$ret"
}
在上面的代码中,退出状态$?
由测试重置[ "$ret" -ne 0 ]
,如果不将其存储在单独的变量中,我们将无法打印它的值,也无法从函数返回它。
另一件需要指出的事情是,你似乎在使用细绳,$command
(未引用),作为您的命令。这将是好多了如果要运行存储在变量中的命令,请使用数组:
thecommand=( awk -F ',' 'BEGIN { "uptime" | getline; split($4,a,": "); if (a[2] > 5) exit 1 }' )
while ! "${thecommand[@]}"; do sleep 5; done
(此示例代码每隔 5 秒休眠一次,直到 1 分钟平均系统负载低于 5。)
请注意,通过使用数组并引用扩展 as "${thecommand[@]}"
,我可以运行命令,而不必担心 shell 如何将字符串拆分为单词并对每个单词应用文件名通配符。
也可以看看我们如何运行存储在变量中的命令?有关您的问题这方面的更多信息。
答案2
你可以这样做:
false; while [[ $? -ne 0 ]]; do
command
done
在这里,false
最初将设置$?
为非零值,允许循环至少运行一次。然后循环运行给定的命令,直到它以零退出状态退出。