shell支持递归吗?

shell支持递归吗?

我正在尝试在 shell 脚本中编写递归函数。考虑以下代码:

function printA {
    if [[ "$1" = 0 ]]; then
        return
    else
        echo "a$(printA $(("$1" - 1)))"
    fi
}

printA 10

function factorial {

    if [[ "$1" = 0 ]]; then
        return 1
    else
        return $(( "$1" * $(factorial $(( $1 - 1 )) ) ))
    fi
}

echo $(factorial 5)    

代码失败:

  • bash(3.0)

recur.sh:第 5 行:“10”- 1:语法错误:需要操作数(错误标记为“”10”- 1”)

A

recur.sh: 第 16 行: "1" * : 语法错误: 需要操作数 (错误标记为 ""1" * ")

recur.sh: 第 16 行: "2" * : 语法错误: 需要操作数 (错误标记为 ""2" * ")

recur.sh:第 16 行:“3”*:语法错误:需要操作数(错误标记为“”3”*”)

recur.sh: 第 16 行: "4" * : 语法错误: 需要操作数 (错误标记为 ""4" * ")

recur.sh: 第 16 行: "5" * : 语法错误: 需要操作数 (错误标记为 ""5" * ")

  • zsh(4.2.1)

printA:1: 错误的数学表达式: 非法字符: "

A

阶乘:5:错误的数学表达式:非法字符:“

然而,它部分成功地使用了ksh88.只有第二个函数失败:

啊啊啊啊啊

recur.sh[5]: 1 * : 预计有更多令牌

recur.sh[5]: 2 * : 预计有更多令牌

recur.sh[5]: 3 * : 预计有更多令牌

recur.sh[5]: 4 * : 预计有更多令牌

recur.sh[5]: 5 * : 预计有更多令牌

  • 我做错了什么吗?
  • bash 和 zsh 是否支持另一种递归语法?
  • 为什么第二个函数 ( factorial) 失败ksh

聚苯乙烯:我知道,递归是邪恶的,性能很差,我应该使用常规循环代替,bla bla bla。我不是在讨论递归是好是坏,而是讨论普通的shell是否支持它。当简单的迭代循环就可以解决问题时,我还没有愚蠢到在生产中发送递归函数:)

答案1

  • 语法错误:算术运算中不使用引号。
  • 逻辑错误:您正在混合 STDOUT 和return值。

将值作为 STDOUT 传递:

function factorial {
    (( $1 )) &&
    echo $(( $1 * $( factorial $(( $1 - 1 )) ) )) ||
    echo 1
}

factorial 5

或者return他们:

function factorial {
    (( $1 )) || return 1
    factorial $(( $1 - 1 ))
    return $(( $1 * $? ))
}

factorial 5
echo $?

两个代码都可以在bash, ksh(当然是 93,不知道 88)和中工作zsh,所以我想是的,shell 确实支持递归。

答案2

递归并不是邪恶的;只要您了解调用函数时内部发生的情况以及陷阱即可。

首先,确保有一个停止条件,该条件将在递归函数完成其任务时执行。如果不这样做,你就没有递归函数,而是无循环。

接下来是变量和重入点。每次调用函数都会将信息推送到堆栈上;重进入点的地址(函数返回时下一条指令的地址)。然后你必须为tge返回值类型保留空间。

接下来是范围问题。变量作为参数传递,局部变量在函数中声明。每次调用函数时,都必须在堆栈上分配此空间,并一直保留在那里,直到返回调用函数时弹出。因此,最终您将耗尽堆栈内存(堆栈溢出情况)。

我为在 DEC Vax 上教授的 Pascal 课程编写了“河内塔”程序。我试图创造一个条件,通过添加我想要的任意数量的杆和环,使我的程序或 VMS 崩溃。我在 3 根杆子上完成了 1000 圈,程序仍然运行。跑了大约10分钟,但是ir跑了。

无论如何,回到你的问题。这里发生的事情似乎是你的变量处于错误的范围内 - 看起来它们是在全局环境中调用的,而不是本地环境中。因此,函数对变量所做的任何更改都会反映在函数的所有实例中。所有更改都需要在本地范围内进行,然后将值返回到调用函数。我不确定像 bash 这样的解释语言是否支持局部变量,并且可以使每个变量对所有脚本的逻辑都可见。

相关内容