bash bash中的递归函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9682524/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 21:46:38  来源:igfitidea点击:

Recursive function in bash

bashfunctionrecursion

提问by FinalDestiny

I want to do a function that will return the factorial of a number in bash

我想做一个函数,它会在 bash 中返回一个数字的阶乘

Here's the current code that doesn't work, can anyone tell me what's wrong and how to correct it? I just started learning bash and I don't know that much.

这是当前无效的代码,谁能告诉我出了什么问题以及如何纠正它?我刚开始学习 bash,我知道的不多。

#!/bash/bin
factorial()
{
  let n=
  if (( "$n" <= "1" ))
  then return 1
  else
  factorial n-1
  return $n*$?
  fi
  return 0
}
factorial 5
echo "factorial 5 = $?"

回答by Daniel Voina

There are several syntax and a quite obvious logic one (return 0)

有几种语法和一个很明显的逻辑(返回0)

A working version is below:

一个工作版本如下:

#!/bin/bash

factorial()
{
    if ((  <= 1 )); then
        echo 1
    else
        last=$(factorial $((  - 1 )))
        echo $((  * last ))
    fi
}
factorial 5

You are missing:

你不见了:

  1. return is bad (should use echo)

  2. shbang line (is /bin/bash not /bash/bin)

  3. Can't do arithmetic outside of (( ))or $(( ))(or let, but (( ))is preferred)

  1. 退货不好(应该使用echo

  2. shbang 行(是 /bin/bash 不是 /bash/bin)

  3. 不能在(( ))or $(( ))(或let,但(( ))最好)之外进行算术运算

回答by user1070300

#!/bin/bash

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

This will work better.

这样效果会更好。

(It works up to 25, anyway, which should be enough to prove the point about recursion.)

(无论如何,它最多可以工作到 25,这应该足以证明关于递归的观点。)

For higher numbers, bc would be the tool to use, making the ninth line above:

对于更高的数字, bc 将是使用的工具,使上面的第九行:

echo " * $(factorial $((  - 1 )))" | bc

but you have to be a bit careful with bc --

但是你必须对 bc 小心一点——

$ factorial 260
38301958608361692351174979856044918752795567523090969601913008174806\
51475135399533485285838275429773913773383359294010103333339344249624\
06009974551133984962615380298039823284896547262282019684886083204957\
95233137023276627601257325925519566220247124751398891221069403193240\
41688318583612166708334763727216738353107304842707002261430265483385\
20637683911007815690066342722080690052836580858013635214371395680329\
58941156051513954932674117091883540235576934400000000000000000000000\
00000000000000000000000000000000000000000

was quite a strain on my poor system!

对我糟糕的系统造成了很大的压力!

回答by kojiro

echo-ing a result may be the only way to get a result for n > 5, but capturing the echo'ed result requires a subshell, which means the recursion will get expensive fast. A cheaper solution is to use a variable:

echo-ing 结果可能是获得 n > 5 结果的唯一方法,但是捕获回显的结果需要一个子外壳,这意味着递归会很快变得昂贵。更便宜的解决方案是使用变量:

factorial() {
    local -i val=${val:-()}
    if ((  <= 1 )); then
        echo $val
        return
    fi
    (( val *=  - 1 ))
    factorial $((  - 1 ))
}

If you want to be extra sure that valis unset when you start, use a wrapping function:

如果您想val在开始时更加确定未设置,请使用包装函数:

factorial() {
    local -i val=
    _fact() {
        if ((  <= 1 )); then
            echo $val
            return
        fi
        (( val *=  - 1 ))
        _fact $((  - 1 ))
    }
    _fact 
}

For comparison:

比较:

# My Method
$ time for i in {0..100}; do factorial $(( RANDOM % 21 )); done > /dev/null 

real    0m0.028s
user    0m0.026s
sys     0m0.001s

# A capturing-expression solution
$ time for i in {0..100}; do factorial $(( RANDOM % 21 )); done > /dev/null 

real    0m0.652s
user    0m0.221s
sys     0m0.400s

回答by Sayan Roy Subho

clear cat

fact()

{

        i=
        if [ $i -eq 0 -o $i -eq 1 ]
        then
                echo 1
        else
                f=`expr $i \- 1`
                f=$(fact $f)
                f=`expr $i \* $f`
                echo $f
        fi
}

read -p "Enter the number : " n

if [ $n -lt 0 ]

then

        echo "ERROR"

else

        echo "THE FACTORIAL OF $n : $(fact $n) "
fi

回答by Andrii Kovalchuk

Another one implementation using echoinstead of return

另一种使用echo代替的实现return

#!/bin/bash

factorial()
{
        if [  -le 1 ]
        then
                echo 1
        else
                echo $[  * `factorial $[-1]` ]
        fi
}
echo "factorial  = " `factorial `

回答by Marc Dechico

#-----------------factorial ------------------------
# using eval to avoid process creation
fac=25
factorial()
{
    if [[  -le 1 ]]
    then
        eval =1
    else

        factorial $[-1] 
        typeset f2
        eval f2=$
        ((f2=f2*))
        eval =$f2

    fi
}
time factorial $fac res 
echo "factorial =$res"