gpt4 book ai didi

bash - 递归调用函数时如何阻止bash创建子shell

转载 作者:行者123 更新时间:2023-11-29 09:00:23 25 4
gpt4 key购买 nike

这是一个计算阶乘的简单 shell 函数。

#!/bin/bash

function factorial()
{
if (( $1 < 2 ))
then
echo 1
else
echo $(( $1 * $(factorial $(( $1 - 1 ))) ))
fi
}

factorial $1

但我发现当给定一个非常大的输入时,这个脚本会创建许多子 shell。这是没有必要的,而且效率不高。有没有什么方法可以在不创建新子 shell 的情况下调用递归函数?

我的目标不是如何在 shell 中编写阶乘函数,而是如何在调用递归定义的函数时避免创建子 shell。

事实上,即使是一个简单的函数调用也会导致子 shell 的创建:

#!/bin/bash

function fac0() {
ps >> log
echo $1
}

function fac1() {
ps >> log
echo $(( $1 * $(fac0 $(( $1 - 1 ))) ))
}

touch log
fac1 $1

运行脚本后,log 文件的内容是:(它仍然创建子 shell)

  PID TTY          TIME CMD
9205 pts/8 00:00:00 bash
9245 pts/8 00:00:00 call_subshell.s
9247 pts/8 00:00:00 ps
PID TTY TIME CMD
9205 pts/8 00:00:00 bash
9245 pts/8 00:00:00 call_subshell.s
9248 pts/8 00:00:00 call_subshell.s
9249 pts/8 00:00:00 ps

由于创建了子 shell,因此存在其他不需要的方面。

#!/bin/bash

declare -i i
i=0

function factorial() {
i=$(($i + 1))
if (( $1 < 2 ))
then
echo 1
else
local c=$(( $1 - 1 ))
echo $(( $1 * $(factorial $c) ))
fi
}

factorial $1
echo $i

无论参数是多少,这个脚本都会打印$i=1!

最佳答案

避免递归:

#!/bin/bash
factorial() {
local f=1
for ((i=2; i<=$1; i++)) ; do
(( f *= i ))
done
echo $f
}

factorial $1

子 shell 是由于命令替换而产生的。使用“参数作为结果”的方式来避免它:

#!/bin/bash

# set -xv

factorial() {
# echo $BASH_SUBSHELL
if [[ $2 ]] ; then
if (( $2 == 1 )) ; then
echo $1
else
factorial $(( $1 * $2 )) $(( $2 - 1 ))
fi
else
factorial $1 $(( $1 - 1 ))
fi
}

factorial $1

关于bash - 递归调用函数时如何阻止bash创建子shell,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33568055/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com