aab*_*aab 2 shell scripting bash shell-script
我想在循环中执行一个命令,直到它以退出代码退出0,所以我尝试了:
$ while/until $?; do $command; done
Run Code Online (Sandbox Code Playgroud)
但until/while似乎只接受布尔值true/false而不是0/1.
我是否错过了类似的[[ ]]东西或其他东西?
Kus*_*nda 15
在while和until关键字需要一个命令作为他们的论点。如果命令返回零退出状态,信号“成功”,while将在循环体运行的命令,同时until将不会在循环体运行的命令。
您的代码似乎使用while和until用$?,最近命令的退出状态,作为一个命令。这将不起作用,除非您在系统上有以整数作为名称的命令。什么会的工作就是使用test命令把它比对0,例如,与
until test "$?" -eq 0; do some-command; done
Run Code Online (Sandbox Code Playgroud)
或者,使用 的缩写形式test,
until [ "$?" -eq 0 ]; do some-command; done
Run Code Online (Sandbox Code Playgroud)
现在的问题显然是$?进入循环时很可能为零,甚至阻止循环运行一次。让命令本身直接将其退出状态提供给whileor会更有意义until(除非您想$?通过false在循环之前调用例如初始化为非零值,这看起来很奇怪)。
使用标准的 POSIX(虽然不是 Bourne,但现在并不重要)shell 语法:
until [ "$?" -eq 0 ]; do some-command; done
Run Code Online (Sandbox Code Playgroud)
或(伯恩和 POSIX),
while ! some-command; do continue; done
Run Code Online (Sandbox Code Playgroud)
这两个都运行,some-command直到它返回零退出状态(“成功”)。在每次迭代中,它都会执行continue循环体内的关键字。立即执行continue跳到循环的下一次迭代,但您可以将其替换为例如sleep 5在每次迭代中都有一个短暂的延迟,或者:什么都不做。
另一种变体是有一个无限循环,当您的命令成功时退出:
until some-command; do continue; done
Run Code Online (Sandbox Code Playgroud)
或者,稍微详细一点,并增加了可读性,
while true; do some-command && break; done
Run Code Online (Sandbox Code Playgroud)
您真正需要使用的唯一时间$?是当您需要跟踪此值一段时间时,如
somefunction () {
grep -q 'pattern' file
ret=$?
if [ "$ret" -ne 0 ]; then
printf 'grep failed with exit code %s\n' "$ret"
fi >&2
return "$ret"
}
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,退出状态 in$?被测试重置,[ "$ret" -ne 0 ]如果不将其存储在单独的变量中,我们将无法打印其值或从函数中返回它。
另一件要指出的事情是,您似乎在使用字符串, $command(未加引号)作为您的命令。这将是更好的,如果你想运行存储在一个变量的命令使用数组:
while true; do
if some-command; then
break
fi
done
Run Code Online (Sandbox Code Playgroud)
(此示例代码每隔 5 秒休眠一次,直到 1 分钟的平均系统负载低于 5。)
请注意如何通过使用数组并将扩展引用为"${thecommand[@]}",我可以运行我的命令而不必担心 shell 如何将字符串拆分为单词并将文件名全局匹配应用于每个单词。
另请参阅我们如何运行存储在变量中的命令?有关您问题的这方面的更多信息。