如何在bash脚本的while test中使用函数返回值

如何在bash脚本的while test中使用函数返回值,bash,Bash,这是我的代码摘要。我使用func中的return\u val与中的“true”之间的比较结果来确定while终止条件。但是回声根本不起作用 #!/bin/bash func(){ a=$1 b=$2 echo $a echo $b if ((a > b)) then return_val="true" else return_val="false" fi } c=1 d=4 whil

这是我的代码摘要。我使用
func
中的
return\u val
中的“true”
之间的比较结果来确定while终止条件。但是回声根本不起作用

#!/bin/bash

func(){
    a=$1
    b=$2
    echo $a
    echo $b
    if ((a > b)) 
    then 
        return_val="true"
    else
        return_val="false"
    fi  
}

c=1
d=4
while [[ $(func $c $d) && ("$return_val"!="true") ]]
do
    ((c++))
done

我宁愿让函数返回一个值

#!/bin/bash

func(){
    a=$1
    b=$2
    echo $a
    echo $b
    if ((a > b)) 
    then 
        return 0 # 0 means success
    else
        return 1 # non-zer0 means failure
    fi  
}

c=1
d=4
until (func $c $d) #While ! success, do something..
do
    ((c++))
done

注意:
func$c$d
周围的括号仅用于可读性。实际上不是必需的。

因为您想查看
echo
命令的输出,所以需要将标准输出与返回(退出)代码分开:

这样,您就可以直接使用函数(前缀为
以否定测试结果),而无需命令替换,并让其返回(退出)代码驱动
的结果,而
循环条件(退出代码为
0
表示成功,其他任何表示失败)

只需使用
!func$c$d
作为条件,
func
的标准输出按原样简单打印


附录:指出不需要严格使用显式的
return
语句来设置退出代码(但不需要使用
test
[1])

((a>b))
本身可以用作函数中的最后一条语句,以隐式设置退出代码:

如果没有显式的
return
语句,则是函数的最后一个命令,用于设置其退出代码(在没有
exit
语句的情况下,同样适用于脚本)

(…)
将退出代码设置为
1
,如果
..
的计算结果为
0
,则设置为
1
(任何非负结果)。如果表达式为真,则诸如
A>b
之类的布尔表达式将导致
1
,否则将导致
0
。因此,
((a>b))
本身做了与上述
if
语句明确做的相同的事情:


[1] 使用
test
[…]
是符合POSIX的评估条件的方法。除非您的代码必须符合POSIX,否则Bash的
[[…]]
(…)
(用于算术布尔测试)是更好的选择-请参阅强制返回0或1不是正确的方法。您希望返回测试的真实退出状态,而不是强制返回状态。如果。。。然后
block

函数自动返回其退出状态。函数的退出状态是final语句的状态。因此,可以将
test
作为
func
中的最终语句

#!/usr/bin/env bash

func(){
    local a=$1 
    local b=$2
    test $a -lt $b  #use exit status directly
}

c=1 
d=4

while func $c $d  #while c is less than d
do
   ((c++)) 
done

@anishane:使用冗余括号会产生创建冗余子shell的效果,因为在bash中括号就是这样做的。总之,IMHO,
而func$c$d;do
是完全可读的(至少在您习惯bash之后是这样)。对不起,回音用于调试。我已经了解到,我们应该返回退出状态而不是值。@CodingTheLife:这正是此解决方案的作用:函数的退出代码决定何时退出循环。独立于此,构成条件的命令产生的任何输出都会被传递。如果不需要该输出,请使用
/dev/null
抑制标准输出,
2>/dev/null
抑制标准输出,并使用
&>/dev/null
抑制两者。既然你的问题说“回声不起作用”——考虑到这个解决方案确实“让它们起作用”,你这么说是什么意思?“这不是做这件事的正确方法。”这是夸张——公认的答案是正确的,但不必赘述<代码>((a>b))
本身就可以作为最后一条语句使用-无需使用灵活性和功能较低的
测试
内置。为了澄清我之前的评论:您的建议是通过简单地让测试结果隐式地确定函数的退出代码来简化代码,这是一个很好的建议。虽然接受答案中的
if
语句实际上是多余的,但它不会屏蔽
(…)
表达式的退出代码,因为
(…)
本身只设置退出代码0或1。(即使存在掩蔽,也只有在随后测试特定的退出代码集时才有意义,这种情况很少发生;在本例中,
只关心0与非零)。
a
b
也是不必要的冗长
func(){test“$1”-lt“$2”}
的工作原理相同,因为您没有修改参数。
func(){
    local a=$1 b=$2
    echo "$a"  # stdout output
    echo "$b"
    (( a > b ))  # exit code implicitly set to 0, if test *succeeds*, 1 otherwise
}
#!/usr/bin/env bash

func(){
    local a=$1 
    local b=$2
    test $a -lt $b  #use exit status directly
}

c=1 
d=4

while func $c $d  #while c is less than d
do
   ((c++)) 
done