如何从创建子shell停止庆典时递归调用一个函数 [英] How to stop bash from creating subshells when recursively call a function

查看:127
本文介绍了如何从创建子shell停止庆典时递归调用一个函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

This is a simple shell function to calculate factorial.

#!/bin/bash

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

factorial $1

不过,我发现,给予了非常大的投入时,该脚本将产生很多的子炮弹。这是没有必要和效率不高。有什么办法来调用递归函数,而无需创建新的子炮弹?

But I find that this script will create many sub-shells when given a very big input. It is not necessary and not efficient. Is there any way to call recursive functions without creating new sub-shells?

我的目标不是如何编写阶乘函数的外壳,但如何避免创建子壳通话时递归定义的功能。

My goal is not how to write a factorial function in shell, but how to avoid creating sub-shells when call recursively defined functions.

在事实上,即使是一个简单的函数调用将导致生成子壳:

In fact, even a simple function call will cause creation of sub-shells:

#!/bin/bash

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

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

touch log
fac1 $1

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

After run the script, the log file's content is: (It still creates sub-shells)

  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创作,其他不需要方面存在的。

Because of sub-shell creation, other unwanted aspects exist.

#!/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 不管理由是什么号码!

This script will print $i=1 no matter what number the argument is!

推荐答案

避免递归:

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

factorial $1

子shell,是因为命令替换的催生。使用的说法,结果的方式来避免:

The subshell is spawned because of command substitution. Use a "argument as a result" way to avoid it:

#!/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

这篇关于如何从创建子shell停止庆典时递归调用一个函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆