• bash函数定义/使用/传参…


    函数:function, 功能
        过程式编程,代码重用
            模块化编程
            简洁
           
        语法:
            function f_name {
                函数体
            }
            或者
            f_name() {
                函数体
            }
       
        调用:使用函数名
            函数名出现的地方,会被自动替换为函数代码;
           
        练习:利用函数改写此前的服务脚本
            启动一个脚本之后,脚本本身会在/var/lock/subsys/目录下创建一个对应的锁文件
            service httpd start启动httpd服务,此时在/var/lock/subsys/目录下,会生成httpd锁文件
            /etc/rc.d/init.d存放服务脚本,遵循的是lsb编写格式
            在/etc/rc.d/init.d中有一个文件functions,为公用的函数
            想要调用functions文件里的各个函数,则添加
            . /etc/rc.d/init.d/functions代码,在你需要调用的文件中
            假如是httpd服务,则需要另外导入 . /etc/sysconfig/httpd 的配置文件
            #!/bin/bash
            #
            #$0是当前脚本的名称
            prog=`basename $0`
            lockfile=/var/lock/subsys/$prog
           
            start() {
                if [ -e $lockfile ];then
                    echo "$prog is already running."
                else
                    touch $lockfile
                    [ $? -eq 0 ] && echo "Starting $prog finished."
                fi
            }
           
            stop() {
                if [ -e $lockfile ];then
                    rm -rf $lockfile
                    [ $? -eq 0 ] && echo "Stoping $prog finished."
                else
                    echo "$prog is stopped yet."
                fi
            }
           
            case $1 in
            "start")
                start ;;
            "stop")
                stop ;;
            "restart")
                stop
                start ;;
            *)
                echo "Usage: $prog {start|stop|restart}"
                exit 1
            esac
           
        函数返回值:
            函数的执行结果返回值:
                函数中使用打印语句:echo, printf
                函数体中OS命令执行结果的输出
           
            函数的退出状态码:
                默认取决于函数体执行的最后一个命令的退出状态码;
                自定义退出状态码:
                    return [0-255]
                    注意:函数体运行时,一旦遇到return语句,函数即返回;
           
            函数可接受参数:
                传递参数给函数,调用函数时,在函数名后给出参数列表即可;
                    例: testfunc arg1 arg2 arg3
                在函数体中可使用$1,$2....来调用传递过来的各参数
                可使用类似脚本的特殊变量
                    $*,$@: 一次性获取参数列表
                    $#: 参数的个数
                    $?: 上一条命令的执行状态或返回状态码
                例:
                #!/bin/bash
                #
                showuserinfo() {
                    [ $# -lt 1 ] && return 1 #参数个数小于1,即没有传递参数

                    ! id $1 &> /dev/null && return 2 #用户名不存在

                    grep "^$1>" /etc/passwd | cut -d: -f7
                    [ $? -eq 0 ] && return 0 || return 3 #前一条命令执行成功,则return 0, 否则return 3
                }

                while true; do
                    read -p "Enter a username: " username
                    [ "$username" == 'quit' ] && break
                    showuserinfo $username
                    [ $? -ne 0 ] && echo "There is something wrong."
                done       
           
        练习:写一个脚本,完成如下功能(使用函数):
        1、提示用户输入一个可执行命令;
        2、获取这个命令所依赖的所有库文件(使用ldd命令);
        3、复制命令至/mnt/sysroot/对应的目录中
            解释:
                假设,如果复制的是cat命令,其可执行程序的路径是/bin/cat,
                    那么就要将/bin/cat复制到/mnt/sysroot/bin/目录中,
                如果复制的是useradd命令,而useradd的可执行文件路径为/usr/sbin/useradd,
                    那么就要将其复制到/mnt/sysroot/usr/sbin/目录中;
        4、复制各库文件至/mnt/sysroot/对应的目录中;
           
        #!/bin/bash
        #
        target=/mnt/sysroot/
        preCmd(){
            #which $1:获取命令的所在目录, 例如which cat
            #which --skip-alias $1: 参数--skip-alias是跳过别名解析,例如which cp和which --skip-alias cp
            if which $1 &> /dev/null; then
                cmdpath=$(which --skip-alias $1)
                return 0
            else
                echo "No such command."
                return 1
            fi
        }
       
        #/bin/cat
        #/mnt/sysroot/bin/cat
        cmdCopy(){
            #dirname $cmdpath: 获取后边参数所在的目录
            cmddir=$(dirname $cmdpath)
            [ -d $target/$cmddir ] || mkdir -p $target/$cmddir
            [ -f $target/$cmdpath ] || cp $target/$cmddir
            return 0
        }
       
        #ldd /bin/cat: 查看cat命令所需的库文件
        libCopy(){
            for lib in $(ldd $1 | grep -E -o "/[^[space::]]+");do
                libdir=$(dirname $lib)           
                [ -d $target/$libdir ] || mkdir -p $target/$libdir
                [ -f $target/$lib ] || cp $target/$libdir
            done
            return 0
        }
       
        main(){
            while true; do
                read -p "Plz enter a command(quit):" cmd
                [ "$cmd" == 'quit' ] && break
                precmd $cmd
                if [ $? -eq 0 ];then
                    cmdCopy $cmdpath
                    libCopy $cmdpath
                fi
            done
        }
        main
       
        变量的作用域:
            本地变量:整个脚本,在脚本的函数中也可调用,也可修改;
            局部变量:函数调用的整个生命周期;
       
        函数递归:
            函数直接或间接调用函数自身
               
                1 1 2 3 5 8 13
                阶乘: 10!
                    n(n-1)!
                    n(n-1)(n-2)!
           
                    阶乘函数:
                    fact() {
                        if [ $1 -eq 0 -o $1 -eq 1 ];then
                            echo 1
                        else
                            echo $[$1*$(fact $[$1-1])]
                        fi
                    }

  • 相关阅读:
    大学生程序猿IT情书“2014爱的告白挑战赛”获奖名单及优秀情书展示系列之
    Codeforces 385C Bear and Prime Numbers
    CSU1659: Graph Center(最短路)
    新版ADT出现appcompat_v7的问题
    @IBDesignable和@IBInspectable
    FTP命令详解
    R语言屏幕输出
    R语言常用基础知识(入门)
    R语言数据类型转换
    使用建议(内部使用)
  • 原文地址:https://www.cnblogs.com/yajing-zh/p/4924122.html
Copyright © 2020-2023  润新知