bash脚本编程之select语句、函数

概述

    承接上篇,继续介绍一下另一个循环语句select,还有脚本中函数的相关内容,分为三个部分:

        1、select语句的介绍和效果演示

        2、脚本函数详解

        3、函数效果举例

第一章    select语句的介绍和效果演示

    1、select 循环与菜单格式

        select VAR in LIST;do

            循环体命令

        done

        select 循环主要用于创建菜单,按数字顺序排列的菜单项将显示在标准错误上,并显示 PS3 提示符,等待用户输入

        用户输入菜单列表中的某个数字,执行相应的命令

        用户输入被保存在内置变量 REPLY 中

    2、select 与 case

        select 是个无限循环,因此要记住用 break 命令退出循环,或用 exit 命令终止脚本。也可以按 ctrl+c退出循环

        select 经常和 case 联合使用

        与 for 循环类似,可以省略 in list , 此时使用位置参量

    3、selcet应用举例

    blob.png blob.png

    blob.png blob.png

    blob.png blob.png

    4、补充:脚本执行时几种执行方式的区别

        .和source来执行脚本与bash 和给脚本执行权限执行的区别:

            . 和source执行脚本时:没有开子进程执行脚本,相当于直接在shell里面运行脚本里面的语句,故运行完脚本,脚本里面的变量在shell里依然有效

            bash或执行权限执行脚本:开了个子进程执行脚本,故脚本里面定义的变量,无法在shell里面继续生效

第二章    脚本中函数详解

    1、函数的基本概念

        函数function是由若干条shell命令组成的语句块,实现代码重用和模块化编程。

        它与shell程序形式上是相似的,不同的是它不是一个单独的进程,不能独立运行,而是shell程序的一部分。

        注意:定义函数的代码段不会自动执行,在调用时才执行

        

    2、函数和shell程序比较相似,区别在于:

        Shell程序在子Shell中运行

        而Shell函数在当前Shell中运行。因此在当前Shell中,函数可以对shell中变量进行修改

        函数在脚本中,相当于在脚本中插入了一段代码,所以函数并不是在脚本的shell中又开一个子shell执行函数,而是跟脚本shell在同一个shell中

    3、函数的定义:

        语法一:

             function FUNCTION_NAME {

                  函数体

                }

        语法二:

              FUNCTION_NAME() {

                  函数体

                }

 

        函数的定义位置:
            可在交互式环境下定义函数
            可将函数放在脚本文件中作为它的一部分
            可放在只包含函数的单独文件中

    4、函数的调用

        在代码中给定函数名即可,函数名出现的任何位置,在代码执行时,都会被自动替换为函数代码

        函数的生命周期:被调用时创建,返回时终止

        可以将经常使用的函数存入函数文件,然后将函数文件载入shell。文件名可任意选取,但最好与相关任务有某种联系。例如: functions.main,一旦函数文件载入shell,就可以在命令行或脚本中调用函数。可以使用set命令查看所有定义的函数,其输出列表包括已经载入shell的所有函数。若要改动函数,首先用unset命令从shell中删除函数。改动完毕后,再重新载入此文件

        载入文件的方式:.  FILENAME或source FILENAME

    5、函数的返回值

        函数有两种返回值:
            函数的执行结果返回值:

            <1> 使用echo或printf命令进行输出

            <2> 函数体中调用命令的输出结果
        函数的退出状态码:

            <1> 默认取决于函数中执行的最后一条命令的退出状态码

            <2> 自定义退出状态码, 其格式为:

                return 从函数中返回,用最后状态命令决定返回值

                    return 0 无错误返回。

                    return 1-255 有错误返回

        return其功能与脚本中exit的功能类似,在函数运行的任何地方,出现return即代表函数终止,即便return的位置不是最后一行,也会退出整个函数,功能与脚本的exit一样,脚本中一旦遇到exit,就退出脚本的运行

    6、删除函数

        unset命令完成此功能.命令格式为:unset FUNCTION_NAME

    7、函数中的参数

        函数可以接受参数:
            传递参数给函数:调用函数时,在函数名后面以空白分隔,给定参数列表即可;例如  FUNCTION_NAME arg1 arg2 …
        在函数体中当中,可使用$1, $2, …调用这些参数;还可以使用$@, $*, $#等特殊变量

    8、函数中的变量

        变量作用域:
            环境变量:当前shell和子shell有效
            本地变量:只在当前shell进程有效,为执行脚本会启动专用子shell进程;因此,本地变量的作用范围是当前shell脚本程序文件,包括脚本中的函数。
            局部变量:函数的生命周期;函数结束时变量被自动销毁

        

            定义局部变量的方法:在函数体中,使用local VAR=VALUE

                这样定义之后,该变量的作用范围就仅仅在函数体内部生效,函数结束,则变量不会影响后续脚本中变量的运行

        注意:如果函数中有局部变量,如果其名称同本地变量, 使用局部变量

    9、函数的递归

        函数的递归:函数直接或间接调用自身

         例如:数学中的阶乘

              N!=N*(N-1)!=N*(N-1)*(N-2)!=…

         这样就可以用函数的递归进行计算

         jc() {

              if [ $1 -eq 0 -o $1 -eq 1 ];then

                  echo 1

              else 

                  echo "$[$1*`jc $[$1-1]`]"

              fi

         }

         例如:斐波那契数列

         1,1,2,3,5,8,13,21…

         第一个值为1,第二个值为1,随后的每一个值都为其前两个数字之和

         求斐波那契数列的第N个数字是多少:(N-1)+(N-2)

         fblq() {

              if [ $1 -eq 1 -o $1 -eq 2 -o $1 ];then

                  echo 1

              else

                  echo "$[`fblq $[$1-1]`+`fblq $[$1-2]`]"

             fi

         }

第三章    函数效果举例

    1、编写服务脚本/root/bin/testsrv.sh,完成如下要求

        (1) 脚本可接受参数:start, stop, restart, status

        (2) 如果参数非此四者之一,提示使用格式后报错退出

        (3) 如是start:则创建/var/lock/subsys/SCRIPT_NAME, 并显示“启动成功”

            考虑:如果事先已经启动过一次,该如何处理?

        (4) 如是stop:则删除/var/lock/subsys/SCRIPT_NAME, 并显示“停止完成”

            考虑:如果事先已然停止过了,该如何处理?

        (5) 如是restart,则先stop, 再start

            考虑:如果本来没有start,如何处理?

        (6) 如是status, 则如果/var/lock/subsys/SCRIPT_NAME文件存在,则显示“SCRIPT_NAMEis running…”如果/var/lock/subsys/SCRIPT_NAME文件不存在,则显示“SCRIPT_NAME is stopped…”其中:SCRIPT_NAME为当前脚本名

        (7)在所有模式下禁止启动该服务,可用chkconfig 和 service命令管理

    #!/bin/bash    
    # Autor: nwc
    # Version: 2.0
    # CreateTime: 2016-08-19
    # Description:
    # 关于第7条的实现,考虑可以将脚本放到/etc/init.d目录下,在脚本开头注释段标明“# chkconfig:运行级别  启动优先级  关闭优先级”    # 然后运行chkconfig  --add 脚本名 --level 指定哪些级别开机启动
    
    FILE=/tmp/$0
    
    START() {
            if [ -f $FILE ];then
                    echo "$0 has been start"        
            else
                    touch $FILE && echo "Start success" || echo "Start fail"
            fi
    }
    
    STOP() {
            if [ -f $FILE ];then
                    rm -rf $FILE && echo "Stop success" || echo "Stop fail"
            else
                    echo "$0 has been stopped"
            fi
    }
    
    RESTART() {
            STOP
            START
    }
    
    STATUS() {
            [ -f $FILE ] && echo "$0 is running..." || echo "$0 is stopped..."
    }
    
    
    read -p "Please input you choice start|stop|restart|status:  " CH
    
    case $CH in
    start)
            START
    ;;
    
    stop)
            STOP
    ;;
    
    restart)
            RESTART
    ;;
    
    status)
            STATUS
    ;;
    
    *)
            echo "bad choice..."
    ;;
    esac

    执行效果如下:

    blob.png

    blob.png

    2、编写脚本/root/bin/copycmd.sh

        (1) 提示用户输入一个可执行命令名称;

        (2) 获取此命令所依赖到的所有库文件列表

        (3) 复制命令至某目标目录(例如/mnt/sysroot)下的对应路径下;

            如:/bin/bash ==> /mnt/sysroot/bin/bash

                /usr/bin/passwd==> /mnt/sysroot/usr/bin/passwd

        (4) 复制此命令依赖到的所有库文件至目标目录下的对应路径下:

            如:/lib64/ld-linux-x86-64.so.2 ==> /mnt/sysroot/lib64/ld-linux-x86-64.so.2

        (5)每次复制完成一个命令后,不要退出,而是提示用户键入新的要复制的命令,并重复完成上述功能;直到用户输入quit退出

    #!/bin/bash    
    # Autor: nwc
    # Version: 2.0
    # CreateTime: 2016-08-19
    # Description:
    
    CMDCP() {
            DIR=`dirname $CmdPath`
            if [ -d ${LuJing}${DIR} ] ;then
                    cp $CmdPath ${LuJing}${DIR} && echo "cp $CMD success" || echo "cp $CMD fail"
            else
                    mkdir -p ${LuJing}${DIR}
                    cp $CmdPath ${LuJing}${DIR} && echo "cp $CMD success" || echo "cp $CMD fail"
            fi    
    }
    
    CMDLIBCP() {   
            for i in ${LibCmd} ; do
                    LIBDIR=`dirname $i`
                    if [ -d ${LuJing}${LIBDIR} ];then
                            cp $i ${LuJing}${LIBDIR} && echo "cp $i success" || echo "cp $i fail" 
                    else
                            mkdir -p ${LuJing}${LIBDIR}
                            cp $i ${LuJing}${LIBDIR} && echo "cp $i success" || echo "cp $i fail" 
                    fi
            done
    }
    
    
    while true;do
         read -p "Input a exec program name like ls/cat... q for quit  " CMD
            case $CMD in
            q)
                    echo "exit..."
                    exit
            ;;
            *)
                    if which --skip-alias $CMD &>/dev/null  && [[ $CMD != "q" ]]; then
                            CmdPath=`which --skip-alias $CMD`
                            LibCmd=`ldd $CmdPath|grep -o -E "/[^[:space:]]+"`
                            LuJing=/tmp/command
                            CMDCP
                            CMDLIBCP
                    else
                             echo "you input is not a right command"
                                    continue
                    fi
            ;;
            esac
    done

      执行效果如下:

    blob.png

    blob.png  

    blob.png

    blob.png

    blob.png

    blob.png

    

原创文章,作者:M20-1倪文超,如若转载,请注明出处:http://www.178linux.com/37714

(0)
上一篇 2016-08-21 20:46
下一篇 2016-08-21 20:46

相关推荐

  • NFS实现共享wordpress

    实验环境 192.168.68.134 wordpress站点 nfs-server 192.168.68.144 nfs-client   实验要求 nfs server共享/var/www/html目录 nfs clinet挂载nfs-server共享的目录,部署wordpress   nfs server端 先部署wordpress…

    Linux干货 2017-10-21
  • nmcli及网络配置

    2017-09-10
  • DNS and BIND

    DNS and BIND 名称解析:把一种代号转换成为另一种代号的功能是应用程序基于某个搜索键在指定的数据库查询,查询到对应的键以后,对应键被找出来的过程!passwd —《nsswith》/etc/nsswith.conf 注意:查询的时候用到的是UDP的53,主从复制走的是tcp(但是也用到udp) DNS: Domain Name Serv…

    Linux干货 2016-10-21
  • httpd的安装与使用

    httpd的安装与使用

    2017-12-07
  • Linux screen命令

    screen命令 一、简介 Screen是一款终端模拟的屏幕管理器,用于命令行终端自由切换。 当我们需要执行一个用时较多的作业,不希望自己或者他人误操作关闭终端导致作业中断,可以进入screen,这样,当终端关闭,作业仍会继续执行。 GNU’s Screen 官方站点:http://www.gnu.org/software/screen/ &nb…

    2017-07-13
  • 循环体

    for 变量名in 列表;do 循环体 done 执行机制: 依次将列表中的元素赋值给“变量名”; 每次赋值后即执行一次循环体; 直到列表中的元素耗尽,循环结束 列表生成方式: (1) 直接给出列表 (2) 整数列表: (a) {start..end} (b) $(seq[start [step]] end) (3) 返回列表的命令  &nbsp…

    Linux干货 2016-08-21

评论列表(1条)

  • 马哥教育
    马哥教育 2016-08-22 12:04

    总结的很详细,作业也完成的很用心,关于shell脚本主要是多抽时间写,看,学习别人的思想,只有养成了编程的思想,才能写出优秀的代码。