我想写一个bash函数,检查文件是否具有某些属性并返回true或false。然后我可以在我的脚本中的“如果”中使用它。但是我应该返回什么呢?

function myfun(){ ... return 0; else return 1; fi;}

然后我这样使用它:

if myfun filename.txt; then ...

当然这行不通。如何才能做到这一点呢?


当前回答

下面是一些测试用例的好例子。

对于基本函数,在方法的最后一行调用true/false,或者使用true;返回以提前退出。

function is_true() { true; }

if is_true; then echo 'true is true'; fi
if ! is_true; then exit; else echo '! true is ! true'; fi

function is_false() { false; }

if ! is_false; then echo 'false is false'; fi
if is_false; then exit; else echo '! false is ! false'; fi

如果不能立即返回,则将返回值存储在变量中。使用(正确;在设置变量时Echo $?)这也适用于嵌套函数(见下一节)。

function from_var() {
        local input=$1
        local my_var
        if ((input == 1)); then
                my_var=$(true; echo $?)
        else
                my_var=$(false; echo $?)
        fi
        echo 'ignore this line'
        (exit $my_var)
}

if from_var 1; then echo "return true is true"; else exit; fi
if from_var 0; then exit; else echo "return false is false"; fi

如果需要存储返回bool类型的函数调用的结果,可以使用相同的技术,但是将调用的输出通过管道传输到/dev/null,或者结果也可能包含来自echo或其他命令的字符串。注意if语句中的(exit $rval)可以让您正确地解释返回值。(其他方法如if (($rval))或if [$rval]将不能正常工作。

# Return a truthy result
rval=$(from_var 1 >/dev/null; echo $?)
if (exit $rval); then echo "return true as variable is true"; else exit; fi

# Return a falsy result
rval=$(from_var 0 >/dev/null; echo $?)
if (exit $rval); then exit; else echo "return false as variable is false"; fi

这段代码的完整输出是:

true is true
! true is ! true
false is false
! false is ! false
ignore this line
return true is true
ignore this line
return false is false
return true as variable is true
return false as variable is false

如果不希望使用> /dev/null抑制函数内的输出,则重写以首先调用该函数。

from_var 0; rval="$?"

其他回答

用0表示真,用1表示假。

示例:

#!/bin/bash

isdirectory() {
  if [ -d "$1" ]
  then
    # 0 = true
    return 0 
  else
    # 1 = false
    return 1
  fi
}


if isdirectory $1; then echo "is directory"; else echo "nopes"; fi

Edit

从@amichair的评论来看,这些也是可能的

isdirectory() {
  if [ -d "$1" ]
  then
    true
  else
    false
  fi
}


isdirectory() {
  [ -d "$1" ]
}
myfun(){
    [ -d "$1" ]
}
if myfun "path"; then
    echo yes
fi
# or
myfun "path" && echo yes

出于代码可读性的考虑,我认为返回true/false应该:

在一条线上 成为一个命令 容易记住 提到关键字return后跟另一个关键字(真或假)

我的解决方案是返回$(true)或返回$(false)如下所示:

is_directory()
{
    if [ -d "${1}" ]; then
        return $(true)
    else
        return $(false)
    fi
}

我遇到了一个问题(没有明确提到吗?)也就是说,不是如何返回布尔值,而是如何正确地计算它!

我想说的是如果[myfunc];然后……,但这是完全错误的。你不能使用括号!如果myfunc;然后……就是这样做的。

正如@Bruno和其他人重申的那样,真和假是命令,而不是值!这对于理解shell脚本中的布尔值非常重要。

在这篇文章中,我解释并演示了使用布尔变量:https://stackoverflow.com/a/55174008/3220983。我强烈建议你去核实一下,因为它们是如此密切相关。

在这里,我将提供一些从函数返回和计算布尔值的示例:

这样的:

test(){ false; }                                               
if test; then echo "it is"; fi                                 

不产生回声输出。(即false返回false)

test(){ true; }                                                
if test; then echo "it is"; fi                                 

生产:

it is                                                        

(即true返回true)

And

test(){ x=1; }                                                
if test; then echo "it is"; fi                                 

生产:

it is                                                                           

因为0(即true)是隐式返回的。

现在,这就是把我搞砸的事情……

test(){ true; }                                                
if [ test ]; then echo "it is"; fi                             

生产:

it is                                                                           

AND

test(){ false; }                                                
if [ test ]; then echo "it is"; fi                             

还生产:

it is                                                                           

在这里使用括号会产生假阳性!(我推断“outer”命令的结果是0。)

从我的帖子中得到的主要信息是:不要像典型的相等检查那样使用括号来计算布尔函数(或变量),例如if [x -eq 1];然后……!

为什么你要关心我说什么,尽管有350+个赞的答案

不是0 =真1 =假。它是:零意味着没有失败(成功),非零意味着失败(类型N)。

虽然所选的答案在技术上是“正确”的,但请不要在代码中返回1**为false。它会有一些不幸的副作用。

有经验的开发人员会把你当成业余爱好者(原因如下)。 有经验的开发人员不会这样做(原因如下)。 它很容易出错。

即使是经验丰富的开发人员也会将0和1分别误认为是假的和真的(基于上述原因)。

它需要(或会鼓励)无关紧要和荒谬的评论。 它实际上不如隐式返回状态有用。

学习一些bash

bash手册说(重点是我的)

返回[n] 导致shell函数停止执行并将值n返回给调用者。如果不提供n,则返回值为函数中执行的最后一个命令的退出状态。

因此,我们不必用0和1来表示真和假。事实上,他们这样做本质上是微不足道的知识,只对调试代码、面试问题和让新手感到惊讶有用。

bash手册还说

否则,函数的返回状态是最后执行的命令的退出状态

bash手册还说

($ ?)展开到最近执行的前台管道的退出状态。

哇,等。管道?让我们再看一遍bash手册。

管道是由一个控制操作符“|”或“|&”分隔的一个或多个命令的序列。

是的。他们说1号命令是一条管道。因此,这三句话的意思是一样的。

$ ?告诉你最后发生了什么。 它会冒出来。

我的答案

虽然@Kambus演示了这样一个简单的函数,根本不需要返回。我认为 与大多数读者的需求相比,这是不切实际的简单。

为什么回来?

如果一个函数要返回它最后一个命令的退出状态,为什么要使用return呢?因为它会导致函数停止执行。

在多种情况下停止执行

01  function i_should(){
02      uname="$(uname -a)"
03
04      [[ "$uname" =~ Darwin ]] && return
05
06      if [[ "$uname" =~ Ubuntu ]]; then
07          release="$(lsb_release -a)"
08          [[ "$release" =~ LTS ]]
09          return
10      fi
11
12      false
13  }
14
15  function do_it(){
16      echo "Hello, old friend."
17  }
18
19  if i_should; then
20    do_it
21  fi

我们这里有…

第04行是一个显式的[-ish]返回true,因为&&的RHS只有在LHS为真时才会执行

第09行返回true或false,匹配第08行的状态

第13行返回false,因为第12行

(是的,这可以打高尔夫球,但整个例子是人为的。)

另一种常见模式

# Instead of doing this...
some_command
if [[ $? -eq 1 ]]; then
    echo "some_command failed"
fi

# Do this...
some_command
status=$?
if ! (exit $status); then
    echo "some_command failed"
fi

Notice how setting a status variable demystifies the meaning of $?. (Of course you know what $? means, but someone less knowledgeable than you will have to Google it some day. Unless your code is doing high frequency trading, show some love, set the variable.) But the real take-away is that "if not exit status" or conversely "if exit status" can be read out loud and explain their meaning. However, that last one may be a bit too ambitious because seeing the word exit might make you think it is exiting the script, when in reality it is exiting the (...) command group subshell.


**如果你坚持使用return 1来表示false,我建议你至少使用return 255来代替。这将导致您未来的自己或任何其他必须维护您的代码的开发人员质疑“为什么是255?”这样他们至少会集中注意力,有更好的机会避免犯错。