【问题标题】:What is the proper way to test a Bash function's return value?测试 Bash 函数返回值的正确方法是什么?
【发布时间】:2011-09-08 15:13:33
【问题描述】:

我想在 if 语句中测试 Bash 函数的返回值,如下所示:

if [[ func arg ]] ; then …

但我收到如下错误消息:conditional binary operator expected.

这样做的正确方法是什么?

是不是下面这个?

 if [[ $(func arg) ]] ; then ...

【问题讨论】:

  • 函数返回什么类型的值?
  • 0 或 1 但如果更好,它可以返回其他内容。
  • 我建议使用函数的退出代码来传递状态信息。

标签: bash function syntax


【解决方案1】:

如果是退出代码而不是结果,你可以使用

if func arg; then ...

如果您不能使函数返回正确的退出代码(使用return N),并且您必须使用字符串结果,请使用Alex Gitelman's answer

$ help if:

if: if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else COMMANDS; ] fi

根据条件执行命令。

if COMMANDS 列表被执行。如果其退出状态为零,则 then COMMANDS 列表被执行。否则,每个elif COMMANDS 列表是 依次执行,如果退出状态为零,则对应的 then COMMANDS list 被执行并且 if 命令完成。否则, else COMMANDS 列表被执行,如果存在的话。退出状态 整个构造是执行的最后一个命令的退出状态,或者为零 如果没有条件测试为真。

退出状态: 返回最后执行的命令的状态。

【讨论】:

  • 太棒了!很难相信正确的方法是最简单的!我对 unix/shell/bash/futureofhumanity 的信心被放大了!
  • 如何测试取反值?
  • @kay 我没有写否定,我写的是否定。你如何测试一个否定的值? if !func arg; 不起作用。
  • @kay 对,我想到了...if func ; then ; else ...; fi 我希望有更好的东西 :) 不过谢谢。
  • @OndraŽižka 有点晚了,但你可以使用:if ! func arg; then echo "func returns non zero"; fi 注意否定运算符和函数调用之间的空格
【解决方案2】:

如果您需要测试两个条件,一个是函数/命令的退出状态,另一个是例如变量的值,使用这个:

if func arg && [[ $foo -eq 1 ]]; then echo TRUE; else echo FALSE; fi

【讨论】:

    【解决方案3】:

    如果函数返回多个单词,似乎会产生此错误。

    例如,1 2

    只是引用它:

    "$(func arg)"
    

    示例:

    $ if [[ 1 2 ]] ; then echo 1 ; fi
    -bash: conditional binary operator expected
    -bash: syntax error near `2'
    $ if [[ "1 2" ]] ; then echo 1 ; fi
    1
    

    如果你比较 0 和非 0,只需使用

    if [[ "$(func arg)" != "0" ]]
    

    【讨论】:

    • @Philipp 好点。我只是习惯单[.我更正了使用 [[.但我倾向于引用所有内容,因此在这种特定情况下可能无关紧要。
    • 除非在陷阱中提到的情况下,旧 shell 不能正确解释以破折号开头的 LHS。
    【解决方案4】:

    在相关说明中,如果函数返回各种退出代码而不是真/假,那么:

    func args; ec=$?      # call function and grab the exit code
                          # it is better to have them on the same line so that a future addition of a command
                          # before the case statement wouldn't break the logic
    case $ec in
      value1) # commands
              ;;
      value2) # commands
              ;;
      *)      # commands
              ;;
    esac
    

    【讨论】:

      【解决方案5】:

      select 在这里提供了很多帮助。

      PS3="What's your choice? (^D to stop choosing): "
      select mainmenuinput in updatesystem installsamba installvsftpd installwebmin configuresambaforactivedirectory quitprogram; do
          case "$mainmenuinput" in
      
          "updatesystem")
              echo "Update System..."
          ;;
      
          "installsamba")
              echo "Installing Samba..."
          ;;
      
          #echo And so forth...
          esac
      done
      
      echo Done
      

      有关select 的帮助,请咨询man bash 并搜索“选择”。不提供任何输入将重复菜单。

      select name [ in word ] ; do list ; done
             The  list  of words following in is expanded, generating a list of items.  The set of expanded words is printed on the standard error, each preceded by a number.  If the in word is omitted, the
             positional parameters are printed (see PARAMETERS below).  The PS3 prompt is then displayed and a line read from the standard input.  If the line consists of a number corresponding  to  one  of
             the  displayed  words, then the value of name is set to that word.  If the line is empty, the words and prompt are displayed again.  If EOF is read, the command completes.  Any other value read
             causes name to be set to null.  The line read is saved in the variable REPLY.  The list is executed after each selection until a break command is executed.  The exit status  of  select  is  the
             exit status of the last command executed in list, or zero if no commands were executed.
      

      样本输出:

      [rinzler ~] $ ./test.sh
      1) updatesystem                      4) installwebmin
      2) installsamba                      5) configuresambaforactivedirectory
      3) installvsftpd                     6) quitprogram
      What's your choice? (^D to stop choosing): 1
      Update System...
      What's your choice? (^D to stop choosing): 2
      Installing Samba...
      What's your choice? (^D to stop choosing):
      1) updatesystem                      4) installwebmin
      2) installsamba                      5) configuresambaforactivedirectory
      3) installvsftpd                     6) quitprogram
      What's your choice? (^D to stop choosing):
      Done
      

      【讨论】:

        猜你喜欢
        • 2019-06-13
        • 2021-10-30
        • 2021-06-25
        • 2020-10-17
        • 2011-04-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-11-05
        相关资源
        最近更新 更多