从 bash 函数返回一个值

从 bash 函数返回一个值

我有一个函数,如果该数字是有效的十位数,则返回 1:

valNum()
{
    flag=1
    if [[ $1 != [1-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] ]]; then
        echo "Invalid Number"
        flag=0
    fi
    return $flag
}

它被调用者:

if [[ $(valNum $num) -eq 1 ]]; then
      #do something
fi

如果数字有效,该函数工作正常,但如果输入无效数字,则显示语法错误。

答案1

@choroba 的答案是正确的,但是这个例子可能更清楚:

valNum $num
valNumResult=$? # '$?' is the return value of the previous command
if [[ $valNumResult -eq 1 ]]
then
  : # do something
fi

这个示例有点长(设置$valNumResult然后查询该值),但更明确地描述了发生的情况:valNum()返回一个值,并且可以查询和测试该值。

PS 请帮自己一个忙,返回0true非零false。这样您就可以使用返回值来指示失败案例中的“我们失败的原因”。

答案2

bash 中的函数只能返回退出代码。相反,命令替换用于获取命令或函数的标准输出。因此,要检查返回的标志,您不需要替换:

if valNum "$num" ; then
    # ...
fi

但是,要使其正常工作,如果数字有效,则应返回 0;如果无效,则应返回 1(退出代码 0 表示没有错误)。

答案3

您不能从 shell 函数返回任意结果。您只能返回一个 0 到 255 之间的整数状态代码。(虽然您可以将更大的值传递给return,但它会以 256 为模被截断。)该值必须为 0 表示成功,为不同的值表示失败;按照惯例,您应该坚持使用 1 到 125 之间的错误代码,因为较高的值具有特殊含义(126 和 127 的外部命令错误,被较高值的信号杀死)。

由于您在此处返回的是或否结果,因此状态代码是合适的。由于flag似乎表示成功或失败,因此您应该使用常规值 0 表示成功,1 表示失败(与您所写的相反)。然后,您可以直接在 if 语句中使用您的函数。

valNum ()
{
  local flag=0
  if [[ $1 != [1-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] ]]; then
    echo 1>&2 "Invalid Number"
    flag=1
  fi
  return $flag
}
if valNum "$num"; then
  #do something
fi

如果需要区分故障代码,请直接调用该函数。返回后,立即可以在 中找到失败代码$?。然后您可以使用 case 语句检查它:

valNum "$num"
case $? in …

如果稍后需要使用状态代码,请在$?被下一个命令覆盖之前将其保存到另一个变量中。

valNum "$num"
valNum_status=$?

您编写的内容不起作用,因为命令替换$(…)扩展到函数的输出,在您的代码中,该输出要么是错误消息,要么是空,never 1

如果您需要传递的信息多于状态代码允许的 shell 函数的信息,您有两种可能性:

  • 在标准输出上打印一些文本,并在命令替换中调用该函数:$(valNum "$num")
  • 分配给函数内的一个或多个变量,并稍后读取这些变量。

答案4

我自己在这个领域得到了相互矛盾的结果。这是我的实证实验的结果。首先,一些‘理论' 关于 bash 或 *nix 命令:

  • 成功==0...即。无错误状态代码)
  • FAIL != 0 ...... 一些状态码

例子:

if  ls -lt /nonexistantdir
then 
    echo "found"
else
    echo "FAIL"
fi
#
echo
ls -lt /nonexistantdir; echo "status = $?"
echo "status = $?"

输出:

ls: cannot access '/nonexistantdir': No such file or directory
FAIL... 

ls: cannot access '/nonexistantdir': No such file or directory
status = 2

如图所示,该ls命令返回状态代码 = 2。当您尝试有效目录时,状态为零(0)。与几乎所有其他语言不同。

规则#1- 制作 ...

  • 正确==0
  • 假!= 0

我们必须记住我们是测试Bashif语句中的错误代码。我设置常量,也可以使用shelltruefalse命令。

TRUE=0
FALSE=1

#  valid number function
#
valNum()
{
    flag=$TRUE

    if [[ $1 != [1-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] ]]; then
        echo "Invalid Number"
        flag=$FALSE
    fi
    return $flag
}

#    later on ...
#
if validNum Abc 
then
    echo "Lucky number"
else
    echo "Not lucky."
fi

和输出:

Invalid Number
Not lucky.

但是,我建议您给出任何 '赞成票' @Gilles 因为他的答案是正确的。我只是想在电子纸上得到简单化的一面。

只是另一件事,test命令。这看起来像:

[[ some-expression ]]; 

大多数时候。例如:

$ test 1
$ echo "result = $?"
result = 0
$ test 0
$ echo "result = $?"
result = 0

零(0)是真的。为什么?那么手册页说单个参数是 '真的' 当它为 NOT-NULL 时。

参考:

相关内容