Bash Script函数中的意外输出



我是bash脚本的新手,我编写了一个脚本,使用一个函数来计算给定数字的阶乘。该函数可以很好地处理零和正数,但不能给出负值的预期输出。

下面是我的脚本:
#!/bin/bash
# factorial program using a function with while loop
calculate_factorial () {
result=1
current=1

if(( $1 < 0 )); then
echo "The number cannot be negative"
elif(( $1 == 0 )); then
echo "1"
else
while(($current <= $1)); do
result=$(( result*current ))
current=$(( current+1 ))
done
#print the result
return $result
fi
}
calculate_factorial $1
echo $result

-8的输出:

The number cannot be negative
1

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

如果我有任何错误,请您指出或解释原因,我将不胜感激。

简短的回答是,这是因为您在函数的开头设置了result=1(请注意,由于result没有声明为局部变量,它是一个全局变量),并在主脚本的末尾设置了echo $resultresult仍然被设置为"1",所以这就是它打印的内容。

更长的答案是你误解了如何从函数返回值。一般来说,函数可以产生三种结果:

  1. 要返回数据(在本例中是阶乘值),应该将其打印到标准输出(也称为stdout,这是默认输出目标)。您可以使用echo或任何其他产生输出的命令。要而不是使用return命令(见下文)。在(( $1 == 0 ))的情况下,这样做是正确的。

    如果在使用该函数时需要捕获输出,可以使用value=$(functname ...args...),但在这种情况下,看起来您只想打印它,因此不需要捕获输出,只需让它直接进入终端。

  2. 要返回错误或状态消息(如"数字不能为负"),将其打印到标准错误(又名stderr)而不是标准输出。您可以使用>&2将命令的输出重定向到标准错误。

  3. 返回成功/失败状态,使用return命令(0=成功,非零=失败)。这是您应该在return命令中返回的所有(类似地,脚本中的exit值)。如果您愿意,可以使用不同的非零值来表示不同的问题,但大多数情况下只使用1来表示所有错误。

    要检查函数的返回状态,要么将其嵌入if语句中,要么在调用函数后立即检查$?(它保存最近命令的状态,因此如果您运行任何其他命令,它将替换它)。

此外,通常良好的脚本卫生是双引号变量和参数引用(例如"$1"而不仅仅是$1),以避免奇怪的解析。也有一些例外,比如在(( ))表达式中。此外,在(( ))或其他算术上下文中,不需要使用$来获取变量的值。Shellcheck.net擅长指出这类问题。顺便说一句,在shell语法中,空格是非常重要的分隔符。使用if(((中间没有空格)是可行的,但是养成像if ((这样分隔元素的习惯要好得多(当然,除非需要分隔而不是,比如var=value)。

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

#!/bin/bash
# factorial program using a function with while loop
calculate_factorial () {
result=1
current=1
if (( $1 < 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 (( $1 == 0 )); then
# Here, we print the result to stdout
echo "1"
# and then return a success status
return 0
else
while (( current <= $1 )); do
result=$(( result*current ))
current=$(( current+1 ))
done
#print the result
echo "$result"
# and then return a success status
return 0
fi
}
calculate_factorial "$1"

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

最新更新