Shell函数

文章详细介绍了Shell脚本中如何定义和使用函数,包括不同定义方式、返回函数值的两种方法、函数参数传递以及递归的应用。此外,还讲解了函数变量的作用范围,并展示了如何创建和使用函数库。示例涵盖了从简单的算术运算到复杂的目录遍历和阶乘计算,深入浅出地阐述了Shell编程中的函数概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

概述

定义Shell函数的方式

函数返回值

返回函数值的方法一

返回函数值的方法二

函数中的传参方式

通过传参自定义计算(10000-100000)*2的值求

函数变量的作用范围

递归

递归阶乘

递归目录

方式一

方式二

函数库


概述

  •  Shell函数是将命令序列按格式写在一起,并且可以方便重复的使用命令序列
  •  也可理解为函数其实就是一串命令的别名

定义Shell函数的方式

[root@localhost ~]# ./16.sh 
3
5
7
9
11
[root@localhost ~]# vim 16.sh

#!/bin/bash
#function q1 {                                    【定义函数方式一】
#w=$[$1 + $2]
#echo $w
#}

q1() {                                            【定义函数方式二】
w=$[$1 + $2]
echo $w
}   【定义函数q1执行“变量w等于参数1+参数2的值”并输出】

for ((q=1;q<=5;q++))
{

q1 $q $q+1
}   【将第一个参数q和第二个参数q+1的值输入到函数q1里进行相关命令的执行】

函数返回值

  •  return表示退出函数并返回一个退出值,脚本中可以用$?变量显示该值
  •  使用原则
    • 1.函数一结束就取返回值,因为$?变量只返回执行的最后一条命令的退出状态码
    • 2.退出状态码必须是0-255,当状态码超出255时则除以256并取余

返回函数值的方法一

[root@localhost ~]# ./17.sh
请输入数值: 500
232                                    【因为输入500,返回值为500*2,超255,所以除256取余】
[root@localhost ~]# vim 17.sh

#!/bin/bash

mfj() {
read -p "请输入数值: " z
return $[$z * 2]

}

mfj
echo $?

返回函数值的方法二

  •  不受返回值255上限

[root@localhost ~]# ./18.sh 
请输入:500
1000
[root@localhost ~]# vim 18.sh

#!/bin/bash

mfj(){

read -p "请输入:" z
echo $[$z * 2 ]


}
mfj1=`mfj`    【用反撇号提取函数qz1输出的值并赋给变量mfj1】
echo $mfj1    【输出变量mfj1的值】

函数中的传参方式

[root@localhost ~]# ./19.sh 
输入第一个参数值:3  
输入第二个参数值:9
12
[root@localhost ~]# vim 19.sh

#!/bin/bash
mfj() {
z=$[$1 + $2]
echo $z

}

read -p "输入第一个参数值:" one
read -p "输入第二个参数值:" two
mfj $one $two

通过传参自定义计算(10000-100000)*2的值求

[root@localhost ~]# ./20.sh 10000 100000
9900110000
[root@localhost ~]# vim 20.sh

#!/bin/bash
mfj() {
mfj2=0
for (z=$1; z<=$2; z++))
do
  mfj2=$[$mfj2 + $z*2]                  【计算公式,并将值赋给mfj2】

done
echo $mfj2  

}

mfj1=`mfj` $1 $2`                    
【这里的参数1和参数2是命令行的位置参数,并将获得到的位置参数输入到函数内进行命令操作。并通过反撇号获取“当函数mfj的参数1和参数2分别是命令行输入的参数结果时的值”】
echo $mfj1   
【最终通过echo输出变量mfj1获取到的值】

函数变量的作用范围

  •  函数在Shell脚本仅在当前Shell环境中有效
  •  Shell脚本中变量默认全局有效
  •  将变量限定在函数内部可使用local命令

[root@localhost ~]# ./21.sh 
9
11
13
2
5
8
2
6
[root@localhost ~]# vim 21.sh

#!/bin/bash
mfj() {           【函数名为mfj】
echo $z          【输出新变量z的值=11】
z=$[$z+2]        【再次定义新z的值为上一个z的值+2】
echo $z          【输出重新定义的变量z值,也就是13】 
z=2              【再次定义变量z=2】
echo $z          【输出刚定义的变量z,也就是2】
z=6              【再次定义变量z的新值为6,但函数内没有echo进行输出操作】
local z          【将变量z限定在函数内部可使用】
z=4              【定义变量z=4】
z=$[$z+1]        【定义新的变量z是上一个z+1的值】
echo $z          【输出新变量z的值,也就是5】
z=8              【再次定义变量z值为8】  
echo $z          【输出刚定义的变量z值为8】 
}

z=9
echo $z          【输出变量z=9的值】
z=$[$z+2]        【重新定义变量z值等于之前z值+2,也就是11】
mfj               【运行函数】

echo $z          【输出函数内定义的z=6值】

递归

  •  递归即函数调用自己本身函数的操作

递归阶乘

  •  一个正整数的阶乘是所有小于及等于该数的正整数的积,并且0的阶乘为1。自然数n的阶乘写作n!
  •  即n!=1×2×3×…×(n-1)×n。阶乘亦可以递归方式定义:0!=1,n!=(n-1)!×n

[root@localhost ~]# ./23.sh 
输入你想要阶乘的数值:10
3628800
[root@localhost ~]# ./23.sh 
输入你想要阶乘的数值:20
2432902008176640000
[root@localhost ~]# vim 23.sh

#!/bin/bash
qz() {                                  【函数名为mfj】
  if [ $1 -ne 1  ];then                 【进行位置参数1(输入的想要阶乘数值num)不等于1的判断】  
    local mfj1=$[$1-1]                   【定义变量mfj1=位置参数1的值-1,并用local进行限定,使其只在函数内部可使用】
    local mfj2=`mfj $mfj1`                 【定义变量mfj2=函数mfj里的变量mfj1命令运行后的结果,并用反撇号进行提取,用local进行限定。
                                          因为每次都需要获得位置参数1减1的值,所以不能直接mfj2=mfj1,需要定义为mfj函数内的mfj1值】
    echo $[$1*$mfj2]                     【输出值为位置参数1*变量mfj2的值】

  else
    echo 1
  fi
}

read -p "输入你想要阶乘的数值:" num
mfj $num                                【将变量num传参到函数mfj内】

递归目录

方式一

  •  用通配符*时则当没有文件或者目录时用*表示

[root@localhost ~]# ./24.sh 
输入你想要查询的目录名:/var/log
/var/log/anaconda: 
...略...
...略...
/var/log/secure-20230714
/var/log/speech-dispatcher: 
 /var/log/speech-dispatcher/ *  【前面2个空格以突显层级关系,通配符*代表该目录中无文件】
/var/log/tallylog
...略...
/var/log/yum.log

[root@localhost ~]# vim 24.sh
#!/bin/bash
mfj() {
for z in $1/ *              【用for循环输出参数1,通配符*代表输入的参数下所有的文件和子目录,并赋值给变量z】
do
  if [ -d $z ];then        【用-d判断变量z是否为目录,因为变量z是输入的绝对路径】
     echo "$2$z: "         【如果条件成立则输出变量z的值,这里的$2在第一次循环时是无值,则没有空格】
     mfj $z " $2"           【调用mfj函数本身,当第二次递归操作时则有1个空格,第三次递归操作则有2个空格,以表示层级关系】  
  else
     echo "$2$z"           【如果条件不成立,则输出第N此递归得到的空格及z的值】
  fi
done
}

read -p "输入你想要查询的目录名:" dir
mfj $dir ""                  【将输入的值进行传参到mfj函数内,第二个位置参数""用来缩进以区分子目录】

方式二

  •  用ls的方式则当没有文件或者目录时无任何显示

[root@localhost ~]# vim 24.sh
[root@localhost ~]# ./24.sh 
输入你想要查询的目录名:/var/log
...略...
...略...
tuned: 
tuned.log
vmware-vgauthsvc.log.0
[root@localhost ~]# vim 24.sh

#!/bin/bash

mfj() {
for z in $(ls $1)
do
if [ -d $1/$z ];then
echo "$2$z: "
mfj $1/$z " $2"
else
echo "$2$z" 
fi

done

}

read -p "输入你想要查询的目录名:" dir
mfj $dir ""

函数库

  •  将经常使用的重复代码封装成函数库文件
  •  函数库一般不直接执行,而是由其他脚本调用

[root@localhost ~]# ./25.sh 132 2
加法的结果为:134
减法的结果为:130
乘法的结果为:264
除法的结果为:66
[root@localhost ~]# ./25.sh 132 0
加法的结果为:132
减法的结果为:132
乘法的结果为:0
除法的结果为:除数不能为0!
[root@localhost ~]# vim mykun.sh    【定义函数库里的相关操作】
#!/bin/bash
echo $[$1 + $2]
}

jianfa() {
echo $[$1 - $2]
}

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

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

[root@localhost ~]# vim 25.sh  【定义函数】

. /root/mykun.sh               【.或者source+脚本路径,因为函数库里定义了/bin/bash,所以这里的调用则不需要再次定义】

a=$1                           【代表命令行里的第一个位置参数】
b=$2                           【代表命令行里的第二个位置参数】
mfj1=`jiafa $a $b`              
【变量mfj1=通过命令行位置参数获取的变量a和变量b的值传参到函数库的jiafa函数里,并通过反撇号提取jiafa函数获得传参后的运行结果】
mfj2=`jianfa $a $b`
mfj3=`chengfa $a $b`
mfj4=`chufa $a $b`

echo "加法的结果为:$mfj1"
echo "减法的结果为:$mfj2"
echo "乘法的结果为:$mfj3"
echo "除法的结果为:$mfj4"

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值