Function函数实例

函数: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

(0)
LiiLii
上一篇 2016-08-21
下一篇 2016-08-21

相关推荐

  • Ansible的常用模块

    command模块: 目的:在指定节点上运行hostname命令 命令:ansible 192.168.1.16 -m command  ‘hostname’copy模块:目的:把主控端/root目录下的a.sh文件拷贝到到指定节点上 命令:ansible 192.168.1.16 -m copy -a ‘src=/roo…

    Linux干货 2017-10-31
  • 高可用集群部署文档

    同学们都很活跃,自己好久没写了,也动动笔,下面文章写着玩的,如有错误请联系(NET7-粤-义薄云天) 高可用集群部署文档   目录: 目录: 1 项目需求: 2 实现方式: 2 拓扑图: 3 系统及软件版本: 3 安装步骤: 4 IP分配: 4 LVS和keepalived的安装和配置: 4 LVS主配置: 4 LVS2备 配置: 7 w…

    Linux干货 2015-08-11
  • 马哥教育网络班21期-第五周课程练习

    第五周作业 1、显示/boot/grub/grub.conf中以至少一个空白字符开头的行; [root@zz ~]# egrep "^[[:space:]]+" /boot/grub/grub.conf 2、显示/etc/rc.d/rc.sysinit文件中以#开头,后面跟至少一个空白字符,而后又有…

    Linux干货 2016-07-29
  • iptables实验3 关于内网外网的地址转换及端口转换

    地址属于内核,而不属于网卡!!!!     网络防火墙的实现(主要是forward链) 172.16.100.68(A)和172.16.100.67(B) 192.168.12.10(B)和192.168.12.77(C)(VNET2) B作为C的网关   配置B主机的网卡一个为192.168.1.72,另一个为172.16.2…

    Linux干货 2016-10-30
  • Python函数式编程指南(二):函数

    这是此系列的第二篇,试图说明在Python中如何更好地使用函数并引导诸位使用函数式的思维进行思考。掌握并应用这些内容,就已经是至少形似的函数式风格的代码了,至于思维么,这个真靠自己。 作者水平有限,如有错漏之处还请指出;转载请注明原作者和原地址:) 2. 从函数开始 2.1. 定义一个函数 如下定义了一个求和函数: def add(x, y): return…

    Linux干货 2015-03-11
  • 浅谈Android应用HTTP框架选型

    我们知道,Android应用主要是通过客户端-服务器的方式进行数据交互,一般在APP开发时可能是一个接口对应一个显示模块,这样的设计会让客户端更新时很麻烦。为了解决这个问题,通常的做法是和服务端之间定义协议,设计显示模式,进而达到实时更新UI界面的目的,增加或删除显示模块时不需要让用户手动更新apk,这种方法最常见的就是在做活动或者广告的时候用到。以我们的优…

    2016-06-22

评论列表(1条)

  • 马哥教育
    马哥教育 2016-08-21 22:02

    函数通过先定义,然后通过函数名来进行调用,同时他实现了代码重用和效率提高,这是一个很重要的shell编程思想,需要多写,多练。