shell函数以及其范围与传参、递归以及创建函数库(简单点!递归的方式简单点!)

shell函数以及其范围与传参、递归以及创建函数库

一、Shell函数

编写shell脚本时,你经常会发现在多个地方使用了同一段代码。如果只是一小段代码,一般也无关紧要。但要在shell脚本中多次重写大块代码段就太累人了。bash shell提供的用户自定义函数功能可以解决这个问题。可以将shell脚本代码放进函数中封装起来,这样就能在脚本中的任何地方多次使用它了。

  • 调用函数

函数是一个脚本代码块,你可以为其命名并在代码中任何位置重用。要在脚本中使用该代码块时,只要使用所起的函数名就行了。

二、创建函数

1.Shell函数格式

第一种格式:

function 函数名 {
命令序列
}

第二种格式:

函数名() {
命令序列
}

2.函数的返回值

return表示退出函数并返回一个退出值,脚本中可以用 $ ? 变量显示该值

使用原则:
1)函数一结束就取返回值,因为$?变量只返回执行的最后一条命令的退出状态码
2)退出状态码必须是0~255,超出时值将为除以256取余

例1:

[root@localhost ~]#vim hs1.sh
[root@localhost ~]#chmod +x hs1.sh #赋予执行权限
[root@localhost ~]#cat hs1.sh #查看脚本内容
#!/bin/bash
function db1 {          #db1是函数名
   read -p "请输入:" value  #value是变量名
   return $[$value * 2]    #直接用value乘以2的值作为返回值
}
#####main#####
db1                       #调用函数db1
echo $?                   #输出上个命令的执行结果返回值
[root@localhost ~]#sh -vx hs1.sh #-v:执行脚本前输出脚本内容;-x:列出执行过程
#!/bin/bash
function db1 {
   read -p "请输入:" value
   return $[$value * 2]
}
db1
+ db1
+ read -p $'\350\257\267\350\276\223\345\205\245\357\274\232' value
请输入:3
+ return 6
echo $?
+ echo 6
6

例2:

[root@localhost ~]#vim hs2.sh
[root@localhost ~]#cat hs2.sh #查看脚本内容
#!/bin/bash
db1() {                  #db1是函数名
read -p "请输入:" value   #value是变量
echo $[$value * 2]      #直接输出2乘value的结果
}
result=`db1`            #把函数得出的值直接赋给变量result
echo $result            #输出result的值
[root@localhost ~]#sh -n hs2.sh #查看脚本有无语法错误
[root@localhost ~]#sh -x hs2.sh #查看脚本执行过程
++ db1
++ read -p $'\350\257\267\350\276\223\345\205\245\357\274\232' value
请输入:10
++ echo 20
+ result=20
+ echo 20
20
[root@localhost ~]#chmod +x hs2.sh #赋给脚本执行权限
[root@localhost ~]#./hs2.sh #执行脚本
请输入:10
20

三、传参

bash shell会将函数当成小型脚本来对待,也就是说它可以像普通脚本那样向函数传递参数。函数可以使用标准的参数环境变量来表示命令行上传给函数的参数。例如,函数名会在$0变量中定义,函数命令行上的任何参数都会通过$1、 2 等 定 义 。 也 可 用 特 殊 变 量 2等定义。也可用特殊变量 2#来判断传给函数的参数数目。

[root@localhost ~]#vim hschuancan.sh
[root@localhost ~]#cat hschuancan.sh #查看脚本内容
#!/bin/bash
sum () {               #函数名为sum
su=$[$1 + $2]         #$1和$2求和以后的值赋给变量su
echo $su              #输出变量su的值
}
#########main##########
sum $1 $2             #这段是主代码,调用函数sum,sum函数名后跟着两个参数$1、$2
[root@localhost ~]#chmod +x hschuancan.sh #赋予执行权限
[root@localhost ~]#sh -n hschuancan.sh  #查是否有语法错误
[root@localhost ~]#./hschuancan.sh 8 9 #脚本后跟两个参数$1是8,$2是9
17                #执行结果是17

执行脚本时后面跟的两个参数传递给脚本中的主体代码也就是sum后跟的两个参数,然后执行函数时,函数再引用主体代码sum后跟着的两个参数,也就是$1和$2

注意:此脚本是先执行主体sum $1 $2,再执行上面定义的函数sum()

四、函数变量的作用范围

  • 函数在Shell脚本中仅在当前Shell环境中有效
  • Shell脚本中变量默认全局有效
  • 将变量限定在函数内部使用local命令
[root@localhost ~]#sh -vx hs3.sh 
#!/bin/bash
abc () {
echo "函数内部第一个i的值:$i"
i=$[$i+1]
echo "函数内部第二个i的值:$i"
local i       #设置局部变量
i=8
echo "内部第三个i的值:$i"
}
######main######
i=9             #全局环境
+ i=9
abc             
+ abc
+ echo $'\345\207\275\346\225\260\345\206\205\351\203\250\347\254\254\344\270\200\344\270\252i\347\232\204\345\200\274\357\274\2329'
函数内部第一个i的值:9  #先i=9作为全局变量的时候调用函数abc,所以这里的i依然是全局变量
+ i=10  #这里i=$[$i+1],依然是全局变量
+ echo $'\345\207\275\346\225\260\345\206\205\351\203\250\347\254\254\344\272\214\344\270\252i\347\232\204\345\200\274\357\274\23210'
函数内部第二个i的值:10 #还没设置局部变量,这是刚刚运算得出的值
+ local i #设置局部变量
+ i=8  #局部变量值为8,不影响外部的全局变量
+ echo $'\345\206\205\351\203\250\347\254\254\344\270\211\344\270\252i\347\232\204\345\200\274\357\274\2328'
内部第三个i的值:8 #局部变量值为8
echo "函数外部i的值:$i"
+ echo $'\345\207\275\346\225\260\345\244\226\351\203\250i\347\232\204\345\200\274\357\274\23210'
函数外部i的值:10  #外部全局变量调用函数以后它的值加1
[root@localhost ~]#cat hs3.sh 
#!/bin/bash
abc () {
echo "函数内部第一个i的值:$i"
i=$[$i+1]
echo "函数内部第二个i的值:$i"
local i       #设置局部变量
i=8
echo "内部第三个i的值:$i"
}
######main######
i=9             #全局环境
abc             
echo "函数外部i的值:$i"

注意:局部和全局是两种变量,可以赋予不同的值,但是可以同名

五、递归阶乘

函数可以调用自己来得到结果,通常递归函数都有一个最终可以迭代到的基准值。递归算法的经典例子就是计算阶乘。一个数的阶乘是该数之前的所有数乘以该数的值,比如5的阶乘:

5! = 5 * 4 * 3 * 2 * 1

使用递归可以简化为下面这种形式:

x! = x * (x-1)!

理解了原理做起来就比较简单了,所以用脚本写出来就是:

以3的阶乘为例

[root@localhost ~]#vim jc.sh 
[root@localhost ~]#cat jc.sh 
fact ()  {
  if [ $1 -eq 1 ] #等于1的时候输出1,不等于的时候进入else
  then 
    echo 1
  else  #下面定义两个局部变量,只在当前函数内部有效
  local temp=$[$1 - 1]
  local result=$(fact $temp)
    echo $[$1 * $result] #当n=3,也就相当于(3*result(2*result(1)))
  fi
}
read -p "请输入:" n
result=$(fact $n)
echo $result
[root@localhost ~]#sh -x jc.sh 
+ read -p $'\350\257\267\350\276\223\345\205\245\357\274\232' n
请输入:3
++ fact 3
++ '[' 3 -eq 1 ']'
++ local temp=2
+++ fact 2
+++ '[' 2 -eq 1 ']'
+++ local temp=1
++++ fact 1
++++ '[' 1 -eq 1 ']'
++++ echo 1
+++ local result=1
+++ echo 2
++ local result=2
++ echo 6
+ result=6
+ echo 6
6

六、递归目录

[root@localhost ~]#vim dgml.sh
[root@localhost ~]#cat dgml.sh 
#!/bin/bash
function list_files () {
for f in `ls $1` 
do
if [ -d "$1/$f" ]
 then
    echo "$2$f"     #如果是目录就输出这个目录,$2为空格是用于区分父子目录
list_files "$1/$f" "  $2"  #如果想区分的明显点,可在$2前面加空格     
else
    echo "$2$f"               #不是目录则输出$f结果
fi
done
}

list_files "/var/log" ""
[root@localhost ~]#./dgml.sh  #执行脚本,目录和子目录分明
anaconda
  anaconda.log
  ifcfg.log
  journal.log
  ks-script-1Pn8cs.log
  ks-script-W4EI_q.log
  packaging.log
  program.log
  storage.log
  syslog
  X.log
audit
  audit.log

七、创建库

[root@localhost ~]#cat hsku.sh 
#!/bin/bash

jiafa () {
echo $[$1 + $2]
}

chengfa () {
echo $[$1 * $2]
}

chufa () {
if [ $2 -ne 0 ];then
    echo $[$1 / $2]
else
    echo "$2不能为0"
fi
}


[root@localhost ~]#cat fuzhi.sh 
#!/bin/bash
. hsku.sh
value1=10
value2=5

result1=`jiafa $value1 $value2`
result2=`chengfa $value1 $value2`
result3=`chufa $value1 $value2`

echo "加法结果为: $result1"
echo "乘法结果为: $result2"
echo "除法结果为: $result3"
[root@localhost ~]#./fuzhi.sh 
加法结果为: 15
乘法结果为: 50
除法结果为: 2

猜你喜欢

转载自blog.csdn.net/qq_35456705/article/details/111878641
今日推荐