章
目
录
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
环境变量可能会出错,导致程序出现各种问题。