函数:function
把一段独立功能的代码当做一个整体,而后为之取一个名字,命令的代码段,即为函数。
注意:
定义函数的代码段不会自动执行,在调用时执行;所谓调用函数,在代码中给定函数名即可
函数名出现的任何位置,在代码执行时,都会被自动替换为函数代码;
过程式编程语言:代码重用即可用到函数
模块化编程
结构化编程
函数使用语法:
语法一:
function f_name{
..函数体
}
语法二:
f_name() {
…函数代码(函数体)
}
函数的生命周期:
每次被调用时创建,返回时终止;
其状态返回结果为函数体中运行的最后一条命令的状态结果
自定义状态返回值,需要使用:return
return:[0-255]
0:成功
1-255:失败
示例:给定一个用户名:取得用户的ID号和默认shell
#!/bin/bash # userinfo() { if id "$username" &> /dev/null;then grep "^$username\>" /etc/passwd | cut -d: -f3,7 else echo "no such user" fi } username=$1 userinfo
示例2:服务脚本框架
#!/bin/bash #模拟创建文件来模拟服务的启动、停止、重启、状态等。 prog=$(basename $0) //将此此脚本文件名当做创建的文件 lockfile=/var/lock/subsys/$prog //函数调用来将脚本文件名创建到/var/lock/subsys/下 ######定义函数、创建文件模拟启动服务############### start(){ if [ -f $lockfile ];then echo "$prog is running yet" else touch $lockfile [ $? -eq 0 ] && echo "start $prog finshed" fi } ######定义函数、删除文件模拟停止服务############### stop(){ if [ -f $lockfile ];then rm -f $lockfile [ $? -eq 0 ] && echo "stop $prog finished" else echo "$prog is not running" fi } ######定义函数、删除文件在创建文件模拟重启服务####### restart (){ if [ -f $lockfile ];then rm -f $lockfile touch $lockfile echo "restart $prog finished" else touch -f $lockfile echo "restart $prog finnished" fi } ######定义函数、查看文件模拟查看服务状态############### status() { if [ -f $lockfile ];then echo "$prog is running" else echo "$prog is stopped" fi } #######定义函数、指定使用方法使用方法########## usage() { echo "Usage: $prog {start|stop|restart|startus}" } ######用case多分支条件语句来进行函数调用######### case $1 in //$1为用户运行此脚本指定参数来进行调用函数。 start) //如果传递参数为start,则调用相对应的start函数。 start ;; stop) stop ;; restart) stop start ;; status) status ;; *) usage exit 1 ;; esac
函数的返回值:
函数的执行结果返回值
函数名出现的地方能够显示代码执行结果
(1)使用echo或printf命令进行输出
(2)函数体中调用的命令的执行结果
函数的退出状态码:
(1)默认取决于函数体中执行的最后一条命令的退出状态码
(2)自定义:return
函数可以接受参数
传递参数给函数时,在函数体中,可以使用$1,$2,…..,引用传递给函数的参数;还可以使用$*、$@引用所有参数,$#引用传递的参数的个数
在调用函数时,在函数名后面可以以空白符分割给定参数列表即可,列如,testfunc arg1 arg2 arg3…. (注意,testfunc 是函数名,arg1 arg2 arg3 是调用函数是传递参数)
示例:添加10个用户
添加用户的功能使用函数实现,用户名做为参数传递给函数
#!/bin/bash # #5:user exists //说明5代表的含义 #####定义函数,功能:创建用户########### addusers() { if id $1 &> /dev/null;then return 5 //如果if判断语句为假,则表示用户存在则不创建,并指定函数返回值为5 else useradd $1 retval=$? //创建用户成功时将返回值保存到变量中,然后在用return命令返回其值。 return $retval //注意,如果不用变量保存其返回值,则在下方调用时不能更准确的判定其是否成功。因为状态返回值是其上一条代码的执行结果返回值。 fi } ######使用for循环语句来循环创建用户################# for i in {1..10};do addusers ${1}${i} //调用函数,创建指定参数的用户1到10, retval=$? //保存指定的函数值 if [ $retval -eq 0 ];then //判断其返回值来输出创建状态,如果为0,则表示创建成功 echo "Add user ${1}${i} finished" elif [ $retval -eq 5 ];then //判断其返回值来输出创建状态,如果为5,则表示其用户存在,在函数体中,我们自己定义了用户存在的函数返回值,如果用户存在,则不会执行创建命令,也就不会生成返回值为0,所以其状态返回值只赋值过一次,就是用户存在时的返回值。 echo "user exist" else echo "Unkown Error" fi done
复习
变量作用域:
函数为代码引入了一个独立新的作用域,在函数内部存在,有效作用范围只在函数内部。
局部变量:
作用域是函数的生命周期,在函数结束时被自动销毁
定义局部变量的方法:local VAR=VALUE
本地变量:
作用域是脚本的声明周期;
作用域是运行脚本的shell进程的生命周期。如果没有在脚本中销毁,则脚本的shell进程结束则变量销毁
示例:本地变量和局部变量的区别
[root@CentOs6 tmp]# vim BianLiang.sh #!/bin/bash # name=tom //脚本内有个name变量,其值为tom setname() { // 定义函数 local name=jerry //定义于其脚本变量相同名的变量,其值为jerry,其中local为定义为局部变量。 #设置局部变量之后,此函数内的变量不会影响到调用它的脚本中的变量。 echo "Function: $name" //输出函数内name变量值 } setname //调用函数 echo "shell:$name" 输出name变量值,下面观察一下效果 #############运行脚本,此时函数输出变量和脚本输出变量各为其自有的,因为我们把函数体内的变量设置为了局部变量,局部变量作用范围为其函数体代码段。############ [root@CentOs6 tmp]# bash BianLiang.sh Function: jerry shell:tom 将函数体内的local去掉 #############运行脚本,此时函数输出变量和脚本输出变量为相同,因为现在函数体内的变量为本地变量,即会影响到当前shell及其脚本中的变量,因为此时函数体内的内容替换到调用的位置之后就相当于再一次为给其相同名的变量(name)重新赋值,所有输出结果为相同(当然这也跟输出变量的位置有关)############ [root@CentOs6 tmp]# bash BianLiang.sh Function: jerry shell:jerry
函数递归:
函数直接或间接调用自身
示例:
阶乘:10的阶乘
10!=10*9!=10*9*8!=10*9*8*7!=…..
n!=n*(n-1)!=n*(n-1)*(n-2)!=……
10!=10*(10-1)!=10*(10-1)*(10-2)=….
[root@CentOs6 tmp]# cat JieChen.sh #!/bin/bash # fact () { if [ $1 -eq 0 -o $1 -eq 1 ];then echo 1 else echo $[$1*$(fact $[$1-1])] fi } fact $1
斐波切数列:
1.1.2.3.5.8.13.21….n-1+n-2
$[$(fab $[$1-1])+$(fab $[$1-2])]
#!/bin/bash # fab () { if [ $1 -eq 1 ];then echo 1 elif [ $1 -eq 2 ];then echo 1 else echo $[$(fab $[$1-1])+$(fab $[$1-2])] fi } for i in `seq 1 $1`;do fab $i done
原创文章,作者:Lii,如若转载,请注明出处:http://www.178linux.com/38162
评论列表(1条)
函数通过先定义,然后通过函数名来进行调用,同时他实现了代码重用和效率提高,这是一个很重要的shell编程思想,需要多写,多练。