44

我想设置一个返回值,以便它进入 while 循环:

#!/bin/bash
while [ $? -eq 1 ]
do
#do something until it returns 0    
done

为了让这个工作,我需要$? = 1在开始时进行设置,但这不起作用。

4

11 回答 11

143

exit您可以通过在子 shell 中使用参数执行来设置任意退出代码。

$ (exit 42); echo "$?"
42

所以你可以这样做:

(exit 1)    # or some other value > 0 or use false as others have suggested
while (($?))
do
    # do something until it returns 0    
done

或者你可以模拟一个do while循环

while 
    # do some stuff
    # do some more stuff
    # do something until it returns 0    
do
    continue  # just let the body of the while be a no-op
done

其中任何一个都可以保证循环至少运行一次,我相信这就是您的目标。

为了完整性,exit每个return都接受一个可选参数,它是一个整数(正数、负数或零),它将返回代码设置为除以 256 后整数的余数。当前 shell(或脚本或子 shell*)使用exit和退出使用 退出函数return

例子:

$ (exit -2); echo "$?"
254
$ foo () { return 2000; }; foo; echo $?
208

* 即使对于由管道创建的子外壳也是如此(除非同时禁用和lastpipe启用作业控制):

$ echo foo | while read -r s; do echo "$s"; exit 333; done; echo "$?"
77

请注意,最好使用break离开循环,但它的参数是要跳出的循环的级别数,而不是返回码。

使用 或set +m禁用作业控制。要启用. 如果您同时执行这两项操作,则前面示例中的循环将导致循环包含的外壳退出,并且不会执行最终的外壳。set +o monitorshopt -u -o monitorlastpipeshopt -s laspipeexitwhileecho

于 2012-05-05T00:58:50.307 回答
25

false总是返回退出代码 1。

#!/bin/bash
false
while [ $? -eq 1 ]
do
#do something until it returns 0    
done
于 2012-05-04T12:56:23.203 回答
12
#!/bin/bash

RC=1

while [ $RC -eq 1 ]
do

  #do something until it returns 0    

  RC=$?
done
于 2012-05-04T11:44:25.297 回答
6

一些答案依赖于重写代码。在某些情况下,它可能是您无法控制的外来代码。

虽然对于这个特定的问题,设置 $? 为 1,但如果需要设置 $? 任何价值——唯一有用的答案是丹尼斯威廉姆森的答案。

一种更有效的方法,它不会产生一个新的孩子(但也不太简洁),是:

function false() { echo "$$"; return ${1:-1}; }
false 42

注意: echo 部分只是为了验证它在当前进程中运行。

于 2015-05-06T17:15:16.133 回答
5

while我认为您可以通过在进入循环之前运行保证失败的命令来隐式执行此操作。

当然,典型的此类命令是false.

于 2012-05-04T11:46:49.217 回答
3

没有找到比一个简单的功能更轻的东西:

function set_return() { return ${1:-0}; }

所有其他解决方案都像(...)[...]可能false包含外部进程调用。

于 2019-03-19T21:05:01.010 回答
2

老问题,但有一个更好的答案:

#!/bin/bash
until
    #do something until it returns success
do
    :;
done

如果您要循环直到某事成功,那么只需在 until 部分中执行该操作即可。您可以将完全相同的代码放入您认为必须放入 do/done 部分的 until 部分。您不必被迫在 do/done 部分中编写代码,然后将其结果传回 while 或 until。

于 2015-07-16T16:55:19.787 回答
2

$?可以包含 0..255 之间的字节值。此范围之外的返回数字将重新映射到此范围,就像应用了按位和 255 一样。

exit value- 可用于设置值,但很残酷,因为它会终止进程/脚本。

return value- 在函数中使用时有些传统。

[[ ... ]]- 适用于评估布尔表达式。

这是一个例子exit

# Create a subshell, but, exit it with an error code:
$( exit 34 ); echo $? # outputs: 34

以下是以下示例return

# Define a `$?` setter and test it:
set_return() { return $1; }
set_return 0; echo $? # outputs: 0
set_return 123; echo $? # outputs: 123
set_return 1000; echo $? # outputs: 232
set_return -1; echo $? # outputs: 255

以下是以下示例[ ... ]

# Define and use a boolean test:
lessthan() { [[ $1 < $2 ]]; }
lessthan 3 8 && echo yes # outputs: yes
lessthan 8 3 && echo yes # outputs: nothing

请注意,当$?用作条件时,零 (0) 表示成功,非零表示失败。

于 2020-04-28T03:52:04.463 回答
1

像这样的东西会是你想要的吗?

#!/bin/bash
TEMPVAR=1
while [ $TEMPVAR -eq 1 ]
do
  #do something until it returns 0
  #construct the logic which will cause TEMPVAR to be set 0 then check for it in the 
  #if statement 

  if [ yourcodehere ]; then
     $TEMPVAR=0
  fi
done
于 2012-05-04T11:50:42.753 回答
0

您可以until用来处理#do something until it returns 0返回 1 或 0 以外的值的情况:

#!/bin/bash

false
until [ $? -eq 0 ]
do
#do something until it returns 0    
done
于 2013-08-12T18:24:34.567 回答
0

这就是我正在使用的

allow_return_code() {
  local LAST_RETURN_CODE=$?
  if [[ $LAST_RETURN_CODE -eq $1 ]]; then
    return 0
  else
    return $LAST_RETURN_CODE
  fi
}

# it converts 2 to 0, 
my-command-returns-2 || allow_return_code 2
echo $?
# 0

# and it preserves the return code other than 2
my-command-returns-8 || allow_return_code 2
echo $?
# 8
于 2021-08-15T04:20:49.807 回答