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

bash函数定义/使用/传参…的更多相关文章

  1. Python函数定义及传参方式

    主要内容:     1.函数初识     2.函数传参方式        (1)位置参数        (2)默认参数        (3)关键参数        (4)非固定传参 一.函数初识 1. ...

  2. 详解Python函数参数定义及传参(必备参数、关键字参数、默认可省略参数、可变不定长参数、*args、**kwargs)

    详解Python函数参数定义及传参(必备参数.关键字参数.默认可省略参数.可变不定长参数.*args.**kwargs) Python函数参数传参的种类   Python中函数参数定义及调用函数时传参 ...

  3. python 函数的定义及传参

    函数是一个通用的程序结构部件,是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 定义一个简单的函数: >>> def test(a): #创建一个函数,函数名是test ...

  4. python定义函数时的参数&调用函数时的传参

    一.定义函数: 1.位置参数:直接定义参数 2.默认参数(或者关键字参数):参数名 = "默认值" 3.位置参数必须在默认参数之前 二.调用函数: 1.按位置传,直接写参数的值 2 ...

  5. c语言-函数的定义及传参

    模块化编程 定义: 数据类型 函数名(型参):如果没有数据类型,默认的为int 值传递 地址传递 嵌套调用 递归调用:直接或间接调用本身函数,求可能栈破裂,求阶乘 #include <stdio ...

  6. 深入理解PHP内核(十二)函数-函数的定义、传参及返回值

    原文链接:http://www.orlion.ga/344/ 一.函数的定义 用户函数的定义从function 关键字开始,如下 function foo($var) {    echo $var; ...

  7. 深入理解PHP内核(六)函数的定义、传参及返回值

    一.函数的定义 用户函数的定义从function 关键字开始,如下 function foo($var) { echo $var; } 1.词法分析 在Zend/zend_language_scann ...

  8. python函数的动态传参.作用域与命名空间

    一.动态传参1.*表示动态传参. 可以接受所有的位置参数传参的时候自动的把实参打包成元组 交给形参 def chi(*food): print(food) chi() # 动态传参可以不传参数 chi ...

  9. ruby中的多线程和函数的关键字传参

    1.实现ruby中的多线程 # def test1 # n = 1 # if n > 10 # puts "test1结束" # else # while true # sl ...

随机推荐

  1. CentOS 6.2安装配置LAMP服务器(Apache+PHP5+MySQL)

    准备篇:   1.配置防火墙,开启80端口.3306端口    vi /etc/sysconfig/iptables    -A INPUT -m state --state NEW -m tcp - ...

  2. Linux环境 Java内存快速查看

    最近生产环境遇到内存老是占用很大的情况,16G的内存Free的内存只剩100多M,仿佛一颗定时炸弹一般,说不定就服务Down了.于是开始网上不断的找查看内存使用的方法.现学现卖,以下通过一个例子来演示 ...

  3. logback整合Logstash

    1.依赖 <dependency> <groupId>net.logstash.logback</groupId> <artifactId>logsta ...

  4. 关于Servlet中的转发和重定项

    一:转发 首先转发属于服务器内部行为,通过浏览器的地址栏是看不到URL变化的.比如说客户端发送一个请求到ServletA,ServletA接收到请求,但是没有能力处理,但是ServletA知道Serv ...

  5. Kendo 单页面应用(一)概述

    Kendo 单页面应用(一)概述 Kendo 单页面应用(Single-Page Application,缩写为 SPA)定义了一组类用于简化 Web 应用(Rich Client)开发,最常见的单页 ...

  6. Kendo UI 初始化 Data 属性

    初始化 Data 属性 前面在介绍准备 Kendo UI 开发环境时我们使用 jQuery 的方法将一个  HTML 元素转换成一个 Kendo UI 控制项: $(“#datepicker”).ke ...

  7. css3实现钟表效果

    利用css3 transform属性刻画钟表的的刻度以及指针的角度,代码如下: <head> <meta charset="UTF-8"> <titl ...

  8. 零基础逆向工程17_PE结构01_PE头解析_手动

    PE文件的两种状态 1.在硬盘中 节省硬盘空间 硬盘对齐 内存对齐 2.在内存中 3.PE磁盘文件与内存映像结构图 PE文件为什么要分节 -- 手动解析:PE文件 分析软件:飞鸽传书http://ww ...

  9. <Android 应用 之路> 聚合数据SDK

    聚合数据介绍 聚合数据是一个为智能手机开发者,网站站长,移动设备开发人员及图商提供原始数据API服务的综合性云数据平台.包含手机聚合,网站聚合,LBS聚合三部分,其功能类似于Google APIS.[ ...

  10. Android RecyclerView使用GridLayoutManager间距设置

    使用RecyclerView设置间距,需要重写RecyclerView.ItemDecoration这个类.有如下的效果图需要实现,间距只有中间的格子和底部的格式之间有.   Paste_Image. ...