Bash 脚本函数中的意外输出

Unexpected Output in Bash Script Function

我是 bash 脚本编写的新手,我编写了一个脚本,使用一个函数来计算给定数字的阶乘。该函数适用于零和正数,但它不能为负值提供预期的输出。

这是我的脚本:

#!/bin/bash

# factorial program using a function with while loop

calculate_factorial () {
        result=1
        current=1



        if((  < 0 )); then
                echo "The number cannot be negative"

        elif((  == 0 )); then
                 echo "1"
        else
                while(($current <= )); do
                        result=$(( result*current ))
                        current=$(( current+1 ))
                done
        #print the result
        return $result
        fi

}

calculate_factorial 

echo $result

-8 的输出:

The number cannot be negative
1

本来应该只输出The number cannot be negative,但我不知道输出的第二行1来自哪里

如果您能指出我的错误或说明原因,我将不胜感激。

echo "The number cannot be negative"更改为result="The number cannot be negative

简短的回答是因为您在函数的开头设置了 result=1(请注意,由于 result 未声明为局部变量,它是一个全局变量),并且在你的主脚本结束echo $resultresult 仍然设置为“1”,所以它打印的就是这个。

较长的答案是您误解了如何 return 来自函数的值。一般来说,函数可以产生三种结果:

  1. 到 return 数据(在本例中为阶乘值),您应该将其打印到标准输出(又名 stdout,这是默认输出目标)。您可以使用 echo 或任何其他产生输出的命令。 不要为此使用return命令(见下文)。在 (( == 0 )) 情况下,您正确地执行了此操作。

    如果在使用函数时需要捕获输出,可以使用value=$(functname ...args...),但在这种情况下看起来你只是想打印它,所以你不需要捕获输出,直接到终端就行了。

  2. 到 return 错误或状态消息(如“数字不能为负数”),将其打印到标准错误(又名 stderr)而不是标准输出。您可以使用 >&2.

    将命令的输出重定向到标准错误
  3. 到return一个success/failure状态,使用return命令(0=成功,非零=失败)。这是 all 你应该在 return 命令中 return (同样,脚本中的 exit 值)。如果需要,您可以使用不同的非零值来指示不同的问题,但大多数情况下所有错误都使用 1。

    要检查函数的 return 状态,可以将它嵌入到 if 语句之类的东西中,或者立即检查 $? 调用该函数后(它保存最近命令的状态,所以如果你 运行 任何 其他命令,那将替换它)。

另外,double-quote variable and parameter references (e.g. "" instead of just </code>) to avoid weird parsing. There are a few exceptions, like inside a <code>(( )) expression. Also, inside (( )) or other arithmetic contexts, you don't need to use $ to get the value of variables. shellcheck.net it good at pointing out things like this. BTW, in shell syntax, spaces are extremely important delimiters. Using if(( (without a space between) happens to work, but it's a much better to get in the habit of separating elements like if (( (except, of course, in cases where they're required not to be separated, like var=value) 的脚本通常是好的。

所以,这是您函数的更正版本:

#!/bin/bash

# factorial program using a function with while loop

calculate_factorial () {
        result=1
        current=1

        if ((  < 0 )); then
                # Here, we print an error message to stderr
                echo "The number cannot be negative" >&2
                # and then return an error status
                return 1

        elif ((  == 0 )); then
                # Here, we print the result to stdout
                echo "1"
                # and then return a success status
                return 0

        else
                while (( current <=  )); do
                        result=$(( result*current ))
                        current=$(( current+1 ))
                done
                #print the result
                echo "$result"
                # and then return a success status
                return 0
        fi

}

calculate_factorial ""