一.函数介绍
在shell脚本中,存在着大量的命令操作,其中有很多命令会进行大量的重复,让代码出现了大量的繁琐步骤,不利于去维护;而函数的出现,可以将常用的命令操作加入到函数中,从而在要使用到的过程中,直接进行传参就可以使用,大大减少了很多繁琐的步骤,减去了很大的不便。
1.函数的作用
避免代码重复,还能将大工程代码分割成多个小的功能模块,方便调用,使得代码更简洁、可读性更强;
2.函数的定义方式
(1)
function 函数名 {
命令序列
...
}
function db1 { #格式
read -p "请输入:" value #命令序列
return $[$value * 2]
}
db1
echo $?
(2)
函数名() {
命令序列
...
}
db1() { #格式
read -p "请输入:" value #命令序列
echo $[$value * 2]
}
result=`db1`
echo $result
调用函数:直接在主代码中使用函数名即可调用函数定于的代码
3.函数的返回值
return表示退出函数并返回一个退出值,脚本中可以用$?变量显示该值
(1)使用原则
【1】在函数里使用 echo 返回值,在函数外使用 变量=$(函数名) 获取返回值
【2】在函数里使用 return 返回值,在函数外紧接着使用 echo $? 获取返回值(只能返回0-255范
围的数值,超出部分为除以255取余数)。
[root@192 day13]# vim 1.sh #添加一个脚本文件
#!/bin/bash #在文件内添加这些内容
db1() { #函数定义的格式
read -p "请输入一个整数:" num
sum=$[$num *2 ]
return $sum
}
########### main ############
db1
echo $?
[root@192 day13]# ./1.sh #使用./路径发布时运行脚本文件;bash 也可以运行文件
请输入一个整数:100 #进行测试,输入100返回200
200
[root@192 day13]# ./1.sh #输入200,返回144,超出255时,除以255取余
请输入一个整数:200
144
其他返回结果的方式
[root@192 day13]# vim 1.sh #添加一个脚本文件
#!/bin/bash #在文件内添加这些内容
db1() { #函数定义的格式
read -p "请输入一个整数:" num
sum=$[$num *2 ]
echo $sum
}
########### main ############
result=$(db1)
echo "函数返回值为 $result"
#如果想要返回值时两倍可以使用doulb
#将最后一条命令改成 echo "函数返回值 doulb后为 $[result * 2] " 即可
4.函数的传参
通过在 调用函数时,后面跟位置参数;在函数体里使用 $1 $2 来引用函数后面跟的位置参数
注意点
(1)函数外的 $1 $2 代表的是执行脚本时,脚本后面的跟的第一个 第二个 位置参数
$# 代表 参数个数
$@ 或 $* 代表 所有参数
#!/bin/bash
#函数的传参
db2() {
sum=$[$1 + $2]
echo $sum
}
########## main ##########
read -p "请输入第一个参数:" num1
read -p "请输入第二个参数:" num2
SUM=$(db2 num1 num2) #db2后面的参数为$1 和 $2
echo "$SUM 等于 $num1 + $num2"
(2)函数体里面的 $1 $2 代表的是调用函数时,函数名后面跟的 第一个 第二个 位置参数
$# 代表 参数个数
$@ 或 $* 代表 所有参数
#!/bin/bash
db3() {
sum=$[$1 - $2] <----------------------- #函数内的 $1 和 $2
echo $sum #是脚本内 main 下面的 SUM 定义的
}
######### main ###########
SUM=$(db3 $2 $1) <----------------- #而 main 下面的 $1 和 $2 是命令后的值定义的
echo "$1 - $2 的值为 $SUM"
[root@192 day13]# bash 2.sh 100 60 #执行脚本
100 - 60 的值为 -40
(3)不管在函数体内还是函数体外,$0 都代表脚本本身
例题:使用函数 输出菱形,并实现可通过输入数值的大小来伸缩菱形的大小
lingxing () { #定义函数
num=$1
for ((a=1; a<=num; a++)) #将中间内容加入函数内
do
for ((i=num; i>a; i--))
do
echo -n " "
done
c=$[(a*2)-1]
for ((b=1; b<=c; b++))
do
echo -n "*"
done
echo ""
done
for ((a=num-1; a>=1; a--))
do
#输出空格正三角
for (( b=num; b>a; b--))
do
echo -n " "
done
#输出倒等腰三角形
c=$[(a*2)-1]
for ((i=1; i<=c; i++))
do
echo -n "*"
done
echo ""
done
}
################ main #################
read -p "请输入大小数值:" NUM
lingxing $NUM
执行效果如下图
4.函数变量的作用范围:
脚本中定义的函数只能在脚本的shell环境有效
脚本中定义的变量默认是在脚本的shell环境中全局有效(即在函数体内外都有效)
在函数体内使用 local 变量 定义的局部变量只能在函数体内有效,且此后此局部变量与函数体外同名的全局变量没有任何关系
#!/bin/bash
#函数变量的作用范围
myfun() {
#后执行函数内的变量
local a #local 定义一个新的变量
a=8 #必须在local后面定义才能生效
echo $a
}
######### main ############### #先执行 main 下面的变量
a=9
myfun
echo $a
5.函数的递归
在函数体里调用函数本身
(1)求阶乘
#!/bin/bash
#求递归求阶乘
fact() {
if [ $1 -eq 1 ];then
echo 1
else
tmp=$[$1 - 1]
res=$(fact $tmp)
echo $[$1 * $res]
fi
}
read -p "请输入一个求阶乘的数值:" num
result=$(fact $num)
echo "$num阶乘的值为 $result"
(2)递归目录
dgdir() {
for i in $(ls $1)
do
if [ -d $1/$i ];then
echo -e "$2$1/$i 为目录"
dgdir $1/$i "\t$2"
else
echo -e "$2$1/$i 为文件"
fi
done
}
例题:执行命令 mdkir -p /root/bin/aa/bb/cc/dd; touch /root/bin/aa/bb/cc/dd/abc.txt,通过脚本输出环境变量PATH所包含的所有目录以及其中的子目录和所有不可执行文件
#/bin/bash
#通过函数递归输出环境变量PATH所包含的所有目录以及其中的子目录和所有不可执行文件
dgdir() {
for a in $(ls $1)
do
if [ -d $1/$a ];then
echo -e "$2$1/$a 为子目录"
dgdir $1/$a "\t$2"
else
if [ ! -x $1/$a ];then
echo -e "$2$1/$a 为不可执行文件"
fi
fi
done
}
############# main ###############
IFS_OLD=$IFS
IFS=$IFS':'
for folder in $PATH
do
echo "$folder 为父目录"
dgdir $folder "\t"
done
执行结果
6.函数库
先将一些常用的函数事先保存在一个特定的函数库文件中,需要使用时,可直接在shell文件脚本文件开头位置用 source 函数库文件 加载函数即可直接使用。
(1)创建函数库
#!/bin/bash
source /opt/day13/myfun.sh
value1=$1
value2=$2
result1=$(jiafa $value1 $value2)
result2=$(jianfa $value1 $value2)
result3=$(chengfa $value1 $value2)
result4=$(qiuyu $value1 $value2)
result5=$(fact $value1 $value2)
echo "加法的结果为 $result1"
echo "减法的结果为 $result2"
echo "乘法的结果为 $result3"
echo "求余的结果为 $result4"
echo "阶乘的结果为 $result5"
添加脚本
运行脚本
vim myfunc.sh #创建函数库
hanshu1() {....}
hanshu2() {....}vim shell.sh #创建脚本
source myfunc.sh #加载函数库文件
hanshu1 #直接调用函数