【问题标题】:Why can a bash function recursively call itself without using local variables?为什么 bash 函数可以在不使用局部变量的情况下递归调用自身?
【发布时间】:2014-06-03 13:39:13
【问题描述】:

我正在用 bash 编写脚本。在这个站点 (http://tldp.org/LDP/abs/html/recurnolocvar.html) 中说“即使不使用局部变量,函数也可以递归调用自身”。但没有解释原因。

有一个涉及斐波那契数列的示例函数。他评论代码不需要是本地的,并问为什么,但没有回答。部分如下图:

Fibonacci ()
{
idx=$1   # Doesn't need to be local. Why not?
if [ "$idx" -lt "$MINIDX" ]
then
echo "$idx"  # First two terms are 0 1 ... see above.
else
(( --idx ))  # j-1
term1=$( Fibonacci $idx )   #  Fibo(j-1)

(( --idx ))  # j-2
term2=$( Fibonacci $idx )   #  Fibo(j-2)

echo $(( term1 + term2 ))
fi
}

斐波那契函数有一个“idx”变量,它可以被连续调用修改,因为连续的“idx”定义没有声明为本地的,因此它应该会影响之前的定义。

该站点上的上一个主题 (http://tldp.org/LDP/abs/html/localvar.html) 表明,如果变量未声明为本地变量(因此默认为全局),那么更改它会反映全局范围的变化。

为什么 bash 函数可以在不使用局部变量的情况下递归调用自身?

【问题讨论】:

  • 建议初学者避免使用ABS,因为这样的误导性解释。

标签: bash function


【解决方案1】:

因为变量实际上是局部的。

进程替换中的命令 ($()) 由子 shell 运行。变量值不会从 subshel​​l 传播回来。所以递归调用不会影响父调用。

子shell中运行的命令是:

  • 进程替换 ($(command))
  • 管道的双方 (command1 | command2)
  • 显式子shell ((command))
  • 后台作业 (command&)
  • (特定于 bash 的)进程重定向(>(command)<(command)

没有方法可以将任何变量值从这些传播回来。

【讨论】:

  • 关于第二个要点,可以使用shopt -s lastpipe 在当前shell而不是子shell中运行管道的最后一个命令。 (这是特定于 bash 的。)
【解决方案2】:

是因为他通过子shell递归调用函数:

term1=$( Fibonacci $idx )   #  Fibo(j-1)

我实际上发现效率低下 对于每个级别的递归,都会调用一个进程并可能导致系统过载。最好使用局部变量。

【讨论】:

  • 它首先是低效的,因为它使用了朴素的指数算法。
猜你喜欢
  • 2011-05-23
  • 1970-01-01
  • 2022-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-19
  • 2012-01-23
相关资源
最近更新 更多