shell脚本之函数的引入
内容预知
1.shell函数的基本知识
1.1 shell函数的个人理解
1.2 定义函数的格式
1.3 查看函数与删除函数(Linux命名行环境中)
1.4 函数的返回值
1.4.1 return 返回值
1.4.2 echo返回值的用法
2.函数的参数传入与变量范围
2.1 函数传参规则
2.2 函数中变量的范围
测试一
测试二
2.2.2 用local重新规定函数变量的范围
测试一
测试二
3.实战演练,使用函数写脚本
3.1 菱形打印(函数版本)
3.2 十进制IP转化二进制(函数版)
4. 递归函数
4.1 递归函数进行阶乘运算
4.2 使用递归函数来读取文件
5.函数库的引用
第一步:搭建函数库
第二步:编写脚本进行调用
第三步:结果测试
总结
1.shell函数的基本知识
1.1 shell函数的个人理解
在shell脚本中,存在着大量的命令操作,其中有很多编写的代码的重复性很高,让代码出现了大量的冗余和繁琐,不易维护和解读。于是引入了函数的方法,我们可以将shell中的函数看作是一个方法,只需要调用它并且进行传参,就可以得出结果,并且还能够多次利用,减少重复代码带来的不便。
shell函数的作用:
1.避免代码重复,减少代码的冗余
2.模块化处理,随调随用,增强代码的可读性和维护性
1.2 定义函数的格式
格式一:
function 函数名 {
命令操作(指令代码)
}
格式二:
函数名 (){
命令操作(指令代码)
}
=================main==============================
定义好函数和编写好内容后,就可以开辟一块main(主方法区),在此范围进行函数的调用
1.3 查看函数与删除函数(Linux命名行环境中)
查看函数 : declare -F
删除函数: unset 函数名
1.4 函数的返回值
1.4.1 return 返回值
1)是函数结束的标识,并且后面跟着的数值(就是返回的状态码,默认情况下的$?是0,而经过return改变后,就会变为return后面跟着的数值)
2)return的返回值范围在1-255之间,超过该范围后会被256取余,取余的结果作为返回码
#!/bin/bash
function test {
echo "这是一个关于return返回值的验证实验"
return 257
}
##################main######################
test
echo $?
返回值的结果:
1.4.2 echo返回值的用法
echo对于linux来讲就是一个万能输出的工具,当return 不能满足我们我们对返回值的需求时,可以强迫echo来充当返回值输出工具
#!/bin/bash
function test2 {
echo "这是echo返回值的验证实验:"
read -p "请任意输入一个数字:" num
echo $[$num+1]
}
result=$(test2)
echo $result
返回值输出结果:
2.函数的参数传入与变量范围
2.1 函数传参规则
脚本函数传参测试:
#!/bin/bash
function test3 {
echo "函数获得第一个参数值:" $1
echo "函数获得第二个参数值:" $2
}
############main###################
test3 $2 $1
输出结果:
将结果代入代码中再次分析:
函数传参的结论:
当脚本里位置变量获取到外部传参数值后,函数此时根据脚本获取参数的位置顺序(来决定函数里位置变量获取数值的顺序)图中因为脚本的$2在$1前面,所以函数中的$1获取的是脚本中$2的值
2.2 函数中变量的范围
2.2.1 函数变量的默认范围
测试一
#!/bin/bash
function test4 {
i=1
echo "输出的函数变量的值为" $i
}
############main##############
i=2
test4
输出结果:
测试二
#!/bin/bash
function test4 {
echo "输出的函数变量的值为" $i
i=1
}
############main##############
i=2
test4
输出结果:
结论:对比测试一和测试可知 函数中的变量默认的情况下为shell脚本环境中的全局变量,影响函数内外的结果,最后输出的函数结果依据获取变量的先后顺序来决定的
2.2.2 用local重新规定函数变量的范围
测试一
#!/bin/bash
function test4 {
i=1
}
############main##############
i=2
test4
echo "输出的变量值为" $i
输出结果:
测试二
#!/bin/bash
function test4 {
local i=1
}
############main##############
i=2
test4
echo "输出的变量值为" $i
输出结果:
延申:
输出结果:
测试结论: 用local定义的函数变量为局部变量,它只会影响到自己所在函数的内的与该变量相关的结果,不影响外界或则其他函数中的变量(即使是同名也不影响)
3.实战演练,使用函数写脚本
3.1 菱形打印(函数版本)
使用函数的方式打印一个菱形,并且能够通过标准输入的方式来控制该菱形的大小
#!/bin/bash
#用来打印菱形上半部分的函数
shang (){
i=1
NUM=$1
while [ $i -le $NUM ]
do
a=$NUM
while [ $a -ge $i ]
do
echo -n ' '
let a--
done
b=1
while [ $b -le $i ]
do
echo -n '*'
let b++
done
c=2
while [ $c -le $i ]
do
echo -n '*'
let c++
done
echo ""
let i++
done
}
#用来打印菱形下半部分的函数
xia (){
let d=$1-1
while [ $d -ge 1 ]
do
e=$1
while [ $e -ge $d ]
do
echo -n ' '
let e--
done
f=$[(2*d)-1]
g=1
while [ $g -le $f ]
do
echo -n '*'
let g++
done
let d--
echo ""
done
}
######################main#####################
read -p "请输入一个数字来控制函数的大小(数字越大菱形越大):" num
shang $num
xia $num
测试结果:
3.2 十进制IP转化二进制(函数版)
使用函数的方式,将标准输入获得十进制IP地址转化为二进制的IP地址
#!/bin/bash
#定义一个用于十进制转化成二进制的函数
function bin {
SUM=''
NUM=$1
for i in {1..8}
do
SUM=$[NUM%2]$SUM
let NUM/=2
done
echo $SUM
}
#定义一个用分割IP的函数
SPT (){
IP=$1
for i in {1..4}
do
num=${IP%%.*}
IP=${IP#*.}
#使用bin函数进行转化
BIN=$(bin $num)
echo -n $BIN.
done
}
####################main##################
read -p "请输入一个十进制的IP地址:" SIP
RES=$(SPT $SIP)
echo "输出的二进制IP为:" ${RES%.*}
输出结果:
4. 递归函数
4.1 递归函数进行阶乘运算
#!/bin/bash
fact() {
if [ $1 -eq 1 ];then
echo 1
else
local temp=$[$1 -1]
local result=$(fact $temp)
echo $[$1 * $result]
fi
}
########## main ##########
read -p "请输入一个要阶乘的数值:" n
result=$(fact $n)
echo $result
递归函数进行阶乘的实际过程(以$1=5为例子):
#fact 5 $1=5 temp=4 result=$(fact 4) echo 5 * $(fact 4)
#fact 4 $1=4 temp=3 result=$(fact 3) echo 5 * 4*$(fact 3)
#fact 3 $1=3 temp=2 result=$(fact 2) echo 5 * 4 * 3*$(fact 2)
#fact 2 $1=2 temp=1 result=$(fact 1) echo 5 * 4 * 3 * 2*$(fact 1)
#fact 1 $1=1
输出结果:
4.2 使用递归函数来读取文件
需求:想要读取/var/log 目录下所有的文件和子目录,并且进行区分输出
在没有函数前,我们会选择用循环的方式来写脚本(但是缺点也显而易见)
但是递归读取,就能很好的实现该需求
#!/bin/bash
function list_dir {
for f in `ls $1`
do
if [ -d "$1/$f" ];then
echo "目录:$2$f"
list_dir "$1/$f" " $2"
else
echo "文件:$2$f"
fi
done
}
########## main ##########
list_dir "/var/log" ""
输出结果:
另外:只要就将第一个位置变量传进的参数改为一个标准输入的变量,就可以查找任意目录下的文件和子目录了
5.函数库的引用
如果我们能拥有,或者编写过很多有价值的函数(能够具体实现某一功能的那种函数),我们在想运用的时候希望能够跨文件调用,这些在Linux中shell脚本也能实现,只要进行函数库文件的搭建,后期就能在编写脚本时进行直接调用
函数库所存文件为普通文件即可,但是函数的格式一定要规范,有能传参的设置。
后面进行调用时可以通过 “.”和“source”来进行跨文件调用
第一步:搭建函数库
[root@localhost xunhuan6]#vim myfunction
#加法函数
jiafa(){
echo $[$1+$2]
}
#减法函数
jianfa(){
echo $[$1-$2]
}
#乘法函数
chengfa(){
echo $[$1*$2]
}
#除法函数
chufa(){
if [ $2 -ne 0 ];then
echo $[$1/$2]
else
echo "除数不能为0"
fi
}
#阶乘函数
jiecheng(){
if [ $1 -eq 1 ];then
echo 1
else
local temp=$[$1 -1]
local result=$(fact $temp)
echo $[$1 * $result]
fi
}
第二步:编写脚本进行调用
#!/bin/bash
#调用函数库
source /xunhuan6/myfunction
#获取输入的两个变量
read -p "请输入第一个正整数:" a
read -p "请输入第二个正整数:" b
#调用函数库中的方法,将值赋予变量
r1=$(jiafa $a $b)
r2=$(jianfa $a $b)
r3=$(chengfa $a $b)
r4=$(chufa $a $b)
r5=$(jiecheng $a)
#输出变量
echo "加法的运算结果为:" $r1
echo "减法的运算结果为:" $r2
echo "乘法的运算结果为:" $r3
echo "除法的运算结果为:" $r4
echo "阶乘的运算结果为:" $r5
第三步:结果测试
总结
1.注意函数中的传参和函数外通过位置变量的传参是不同的(函数传参是根据脚本变量的位置决定)
2.注意局部函数变量和全局函数变量的差异
3.接收位置位置变量值,建议赋予新定义的变量,增强代码的可读性
4.理解递归函数,是对函数进行更深层次的利用和挖掘,尤其是递归运用的方面
5.搭建函数库要注意在文件中也要保持函数该有的脚本格式,另外调用时先声明调用的文件,用source或者“.”