if中的if语句和调用函数使用bash

if中的if语句和调用函数使用bash,bash,testing,if-statement,Bash,Testing,If Statement,我编写了一个函数: check_log(){ if [ -f "/usr/apps/appcheck.log" ] then return 1 else return 0 fi } 然后在“if”条件下调用此函数: if [ check_log ]; then ........statements.... fi 这样行吗?我在这里感到困惑,因为bash在成功时返回0,在失败时返回1,但我的函数返回1,条件是检查1/0

我编写了一个函数:

check_log(){
    if [ -f "/usr/apps/appcheck.log" ]
    then
         return 1
    else
         return 0
    fi
}
然后在“if”条件下调用此函数:

if [ check_log ];
then
    ........statements....
fi
这样行吗?我在这里感到困惑,因为bash在成功时返回0,在失败时返回1,但我的函数返回
1
,条件是检查
1
/
0
,它得到
1
,应该给出失败,但在我的shell脚本中,条件是通过的

有人能解释这个问题吗

if [ check_log ];
使用方括号时,调用的是
test
命令。它相当于
if-test-check\u-log
,它是
if-test-n-check\u-log
的简写,意思是“if
”check\u-log“
不是空字符串”。它根本不调用您的
check\u log
函数

将其更改为:

if check_log;
顺便说一下,函数可以更简单地写为:

check_log() {
    ! [ -f "/usr/apps/appcheck.log" ]
}

函数的返回值是最后一个命令的退出状态,因此不需要显式返回语句。

正如@john kugelman所指出的,一种解决方案(也许是最正确的方案)是使用以下语法:

if check_log;
但另一种解决办法是:

if [[ $(check_log; echo $?) -eq 0 ]];
我个人的偏好是后者,因为它促进了条件语句之间的一致性。但缺点是,由于它依赖于命令替换,它将派生一个子进程(即子shell),而第一个方法不会这样做

有关这一主题的有趣读物可在此处找到:

更新(2020-12-01):在大多数情况下,由于效率低下和可能触发错误结果的原因,不建议使用上述替代解决方案,尤其是在被调用函数写入stderr或stdout且输出未被捕获的情况下


更新(2017-10-20):取消我对第二种方法的偏好,因为这些天我的任务是防止不必要的分叉。第一种解决方案中的语法对于非shell编程来说不是那么直观,但它肯定更有效。

如果[6]执行某项操作,如果[0]执行某项操作,那么数字又如何nothing@JumpOffBox如果要进行数值测试,必须使用测试命令的一个数值运算符,如
If[6-ne 0];然后…
。但请注意,您不能使用函数来代替其中一个数字;您应该将shell函数视为命令(可以成功或失败),而不是数学函数(其主要目的是返回值)。@Gordondavison请不要建议明确针对bash而不是/bin/sh的人使用
[]
((7!=0))
更具可读性(也更不容易出错;
(())
,如
[[]]
,会抑制字符串拆分和全局扩展,因此即使使用意外的数据值,也不必使用引号来确保语句按预期进行分析)。如果[any number]执行某些操作,如果[0],那么数字会怎么样在bash中,您可以使用数字上下文来实现这一点——不是
[]
[[]]
,而是
(())
——就像这样:
如果((变量));然后…
只有在
变量
包含大于0的数字时才会计算为true…顺便说一句,“使用bash”时,请确保您的shebang是
#/bin/bash
#/usr/bin/env bash
,而不是
#/bin/sh
;如果是后者,并不是所有的BASH特性都能被启用,那么这里给出的所有建议都不会有效。为什么在世界上你更喜欢第二个建议?如果你不再建议这个答案中给出的实践,你可以考虑删除它。我们有了新的问题,如果没有的话会更好。@CharlesDuffy我不认为删除其他人可能已经加入书签的答案是最好的做法。另一种解决方案在语法上仍然是正确的,它只是碰巧为求值派生了一个子shell,这可能是可取的,也可能是不可取的。生成子shell是一个轻量级的过程,而且这种模式非常普遍。答案不仅是效率低下,而且存在缺陷。如果
check_log
写入标准输出,则无论实际退出状态如何,它写入的任何内容都会在
-eq
的左侧结束,并导致测试失败。在任何情况下,这都不是一种好的做法——即使您想要显式地测试
$?
(比如,在特定的范围内),最好使用不同的语法——例如
if check\u log;[“$?”-lt 3];然后,
@CharlesDuffy很有趣。我没有考虑到可能会有输出到STDUT(检查日志不这样做)。如果[[$(检查日志>/dev/null;echo$?)-lt 3]],重定向输出可以解决这种情况;然后,但仍然效率低下,容易出现您建议的问题。至于从来没有一个案例,我认为这有点苛刻,也许从来没有在您的用例中,或者也许其他许多用例中更合理。更新答案,引导人们走向另一个方向。