如何使用shell脚本实现N次递归

后端 潘老师 3个月前 (02-05) 56 ℃ (0) 扫码查看

shell脚本是一个强大的工具,掌握它能让我们高效地完成各种自动化任务。今天,就来和大家探讨一个有趣又实用的话题——用shell完成N次递归,即便你是个新手,看完这篇文章,也能像技术大牛一样轻松驾驭!

一、前言

可能有些朋友心里犯嘀咕了,递归到底是什么呢?简单来说,递归就是程序调用自身的过程。这就好比你站在两面相对的镜子中间,镜子里的影像会不断反射,无穷无尽,程序中的递归也是类似的原理。那在shell中,该怎么实现递归呢?别着急,接下来就为大家揭晓答案。

二、实现方法

在深入探讨递归实现之前,我们得先了解一下Linux中shell的$0参数。乍一看,$0这个参数好像没什么特别的,它通常指向用户执行的shell可执行文件的地址,既不能是数字,也不能是普通字符串,感觉有点局限。但就是这个看似平平无奇的参数,在递归操作中却有着大作用!

想象一下,如果不用$0参数来写递归代码,可能会写成这样:

/root/dg.sh `expr $1 + 1`

这种写法存在一个问题,一旦root管理员把dg.sh这个可执行文件移动到其他位置,或者给它改个名字,代码就会报错,是不是很不“靠谱”?这就体现出$0参数的优势了。如果把代码前面的/root/dg.sh换成$0,只要这个文件存在,不管它在哪里、叫什么名字,都能正常运行。实际的递归代码是这样的:

$0 `expr $1 + 1`

可能你会好奇,为什么这个看起来没什么用的$0参数,能让递归操作变得这么便捷呢?奥秘就在于,当用户执行这段代码时,$0会指向用户正在执行的包含这段代码的可执行文件。这样一来,就可以再次调用这个文件,从而实现递归效果。现在,只要执行这段代码,递归就完成啦!

掌握了这个技巧,我们还能基于它创作出各种有意思的代码。比如,下面这个类似while循环的代码:

#!/bin/bash
if [ 0 -lt $2 ]
then
    echo $1
    $0 $1 `expr $2 - 1`
fi

再比如,用它来编写一个打印宽度为5的长方形的程序代码:

#!/bin/bash
if [ 0 -lt $1 ]
then
        for i in {1..5}
        do
            # 不换行
            printf '*'
        done
        # 换行
        echo
        $0 `expr $1 - 1`
fi

不过,在使用递归的时候,有个地方需要特别注意。如果递归次数过多,系统会给出这样的警告:

/bin/bash: warning:shell level (1000) too high,resetting to 1

这是在提醒我们,程序递归的次数太多,系统递归中shell程序的层级超过了1000层。一旦出现这种情况,shell系统会把递归中的shell程序层级数重置为1,这就可能导致表示递归中shell程序层级数的$SHLVL环境变量出现错误,进而引发程序中的bug。

看下面这个例子:

#!/bin/bash
echo $1
if [ $1 -le 2000 ]
then
        $0 `expr $1 + 1`
fi
echo "end$SHLVL"

 

这个程序的目的是在几千次递归结束后,打印出递归中shell程序的层级数。但实际执行并递归结束后,打印出来的内容却是这样的:

2000
2001
end5

很明显,$SHLVL环境变量的值出错了。所以说,递归虽好,但不能过度使用,尽量把递归次数控制在几百次以下比较稳妥。

三、总结

通过上面的介绍,大家应该清楚了,在shell中利用$0参数就能轻松实现递归操作。这是因为$0参数会指向用户执行的程序文件,借助它可以再次执行该可执行文件,从而达成递归的目的。不过一定要记住,递归次数不宜过多,否则$SHLVL环境变量可能会出错,导致程序出现各种问题。


版权声明:本站文章,如无说明,均为本站原创,转载请注明文章来源。如有侵权,请联系博主删除。
本文链接:https://www.panziye.com/back/13242.html
喜欢 (0)
请潘老师喝杯Coffee吧!】
分享 (0)
用户头像
发表我的评论
取消评论
表情 贴图 签到 代码

Hi,您需要填写昵称和邮箱!

  • 昵称【必填】
  • 邮箱【必填】
  • 网址【可选】