这里有两个问题。首先,所有变量都是全局变量,这意味着当您进行递归调用时,它会覆盖nr
, rez
, rez1
, and rez2
。您可以通过将它们声明为来解决此问题local
:
fib() {
local nr rez rez1 rez2
if [ $1 -eq 1 -o $1 -eq 2 ]; then
return 1
else
let nr=$1-1
fib $nr
rez1=$?
let nr=$1-2
fib $nr
rez2=$?
let rez=$rez1+$rez2
return $rez
fi
}
第二个问题是您试图通过函数的返回状态传递一个数字。返回状态是一个 1 字节无符号整数,这意味着它不能大于 255(之后它回绕到 0。它的真正目的是给出成功/失败结果(也许还有一些有关失败的信息), 0 表示成功,其他任何内容表示错误。尝试将其用于其他用途是自找麻烦。您可以在此处查看结果(来自local
函数的简化版本):
$ fib 11; echo $?
89
$ fib 12; echo $?
144
$ fib 13; echo $?
233
$ fib 14; echo $?
121
第 14 个斐波那契数是 377,但超过了 255,因此结果为 377-256 = 121。要解决此问题,请通过以下方式返回结果echo
将其发送到标准输出并捕获它$( )
:
fib() {
local nr rez rez1 rez2
if [ $1 -eq 1 -o $1 -eq 2 ]; then
echo 1
else
let nr=$1-1
rez1=$(fib $nr)
let nr=$1-2
rez2=$(fib $nr)
let rez=$rez1+$rez2
echo $rez
fi
}
...不过,这确实有一个缺点:速度慢得多,因为每次调用fib
必须作为子进程运行,并且创建子进程的计算成本很高。 (这实际上可以解决全局变量问题,因为变量向下继承到子流程,而不是向上继承;但这只是偶然解决的。)
重要教训:shell 脚本不是适合此类事情的语言。