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)
现在的问题显然是$?
进入循环时很可能为零,甚至阻止循环运行一次。让命令本身直接将其退出状态提供给while
or会更有意义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 如何将字符串拆分为单词并将文件名全局匹配应用于每个单词。
另请参阅我们如何运行存储在变量中的命令?有关您问题的这方面的更多信息。