四、函数变量的作用范围
函数在shell脚本中仅在当前shell脚本环境中有效(用source执行脚本,在当前系统shell环境运行)
shell脚本中变量默认全局有效
将变量限定在函数内部使用local命令
#!/bin/bash i=8 i=9 echo $i #输出9,因为i的值被覆盖了
#!/bin/bash myfun() { i=9 } ########## main ########### myfun i=8 echo $i #输出8 #主函数开始运行,第一步函数调用i=9,然后i=8覆盖后输出
#!/bin/bash myfun() { i=9 echo $i } ########## main ########### myfun i=8 echo $i #输出98 #调用函数时输出函数里面i=9,而后输出的i被i=8覆盖
#!/bin/bash myfun() { local i #local定义的变量只能在local之后到函数结束前有效 i=9 echo $i } ########## main ########### i=8 myfun echo $i #输出98,而不是99 #local限定了函数i的值,函数外不能重新覆盖,而没有local的变量时全局有效的
五、递归
简单来讲递归就是不停地调用本身,比较有名的递归算法有斐波拉契数列、汉诺塔等,有兴趣的小伙伴可以自行查阅资料了解一下
示例1:求阶乘
#!/bin/bash #使用递归计算阶乘 fact() { if [ $1 -eq 1 ] #$1,表示函数后面调用的变量,如果调用的值是1,输出值就是1 then echo 1 else local temp=$[$1-1] #定义一个变量temp为传入函数的参数减1,并且为局部变量 local result=$(fact $temp) #每次调用函数自己,每次temp减1,直到为1 echo $[$1 * $result] #用c语言理解就是这样一个过程: num*fact(num-1) fi } ##### main ##### read -p "请输入一个正整数:" num result=$(fact $num) #跟上面的result不影响,上面的result是局部变量,仅在函数内有效 echo "$num 的阶乘为: $result"
实现过程
fact 5 $1=5 temp=4 result=$(fact 4) echo 5 * $(fact 4) $1=4 temp=3 result=$(fact 3) echo 5 * 4*$(fact 3) $1=3 temp=2 result=$(fact 2) echo 5 * 4 * 3*$(fact 2) $1=2 temp=1 result=$(fact 1) echo 5 * 4 * 3 * 2*$(fact 1) $1=1 2*1
示例2:递归目录
mkdir -p /root/bin/aa/bb/cc/dd ; touch /root/bin/aa/bb/cc/dd/abc.txt
递归/root/bin目录,显示他的所有子目录和文件
#!/bin/bash #递归/root/bin目录,显示他的所有子目录和文件 list() { for fd in $1/* #逐个检查$1参数指定目录下的所有文件或子目录 do if [ -d $fd ] #判断如果是目录就输出,并且通过递归把这个目录下的所有文件或子目录再逐个检查,如果发现还有子目录会按照这个方式一直检查下去 then echo "$fd 是目录" list "$fd" #递归函数调用 else echo "$fd 是文件" fi done } ##### main ##### list "/root/bin"
六、函数库
可以事先创建一个函数库,在里面定义各种常用的函数然后可以在别的shell脚本中直接引用
#函数库 jiafa() { echo $[$1 + $2] } jianfa() { echo $[$1 - $2] } chengfa() { echo $[$1 * $2] } chufa() { if [ $2 -eq 0 ] then echo "除数不能为0" else echo $[$1 / $2] fi } fact() { if [ $1 -eq 1 ] then echo 1 else local temp=$[$1-1] local result=$(fact $temp) echo $[$1 * $result] fi }
一定要在脚本中加载函数库,用source或者点(.)
七、总结
定义函数法一:
function 函数名 {
命令序列
}
定义函数法二:
函数名(){
命令序列
}
注意:
同名函数 后一个生效
调用函数一定要先定义