• Shell编程—创建函数


    1基本的脚本函数

    函数是一个脚本代码块,你可以为其命名并在代码中任何位置重用。要在脚本中使用该代码块时,只要使用所起的函数名就行了。

    1.1创建函数

    有两种格式可以用来在bash shell脚本中创建函数。第一种格式采用关键字function,后跟分配给该代码块的函数名。

    function name { 
        commands 
    }

    二种格式更接近于其他编程语言中定义函数的方式。

    name() {
         commands                                                   
    }

    1.2 使用函数

    $ cat test1 
    #!/bin/bash 
    # using a function in a script 
    function func1 {    
       echo "This is an example of a function" 
    }  
    count=1 
    while [ $count -le 5 ] 
    do
        func1    
        count=$[ $count + 1 ] 
    done  
    echo "This is the end of the loop" 
    func1 
    echo "Now this is the end of the script" 
     
    $ ./test1 
    This is an example of a function 
    This is an example of a function 
    This is an example of a function 
    This is an example of a function 
    This is an example of a function 
    This is the end of the loop     

    函数定义的位置一定要在使用到该函数的位置之前。

     

    2返回值

    2.1默认退出状态码

    默认情况下,函数的退出状态码是函数中最后一条命令返回的退出状态码。在函数执行结束后,可以用标准变量$?来确定函数的退出状态码。

    $ cat test4 
    #!/bin/bash 
    # testing the exit status of a function 
     func1() {
         echo "trying to display a non-existent file"    
         ls -l badfile 
    }     
    echo "testing the function: " 
    func1 
    echo "The exit status is: $?" 
    
    $ ./test4 
    testing the function: 
    trying to display a non-existent file 
    ls: badfile: No such file or directory 
    The exit status is: 1 

    函数的退出状态码是1,这是因为函数中的最后一条命令没有成功运行。但你无法知道函数中其他命令中是否成功运行。看下面的例子:

    $ cat test4b
    #!/bin/bash
    # testing the exit status of a function
     func1() { 
        ls -l badfile   
         echo "This was a test of a bad command"
    }  
    echo "testing the function:" 
    func1 
    echo "The exit status is: $?"
    
    $ ./test4b 
    testing the function:
    ls: badfile: No such file or directory
    This was a test of a bad command
    The exit status is: 0

    这次,由于函数最后一条语句echo运行成功,该函数的退出状态码就是0,尽管其中有一条命令并没有正常运行。

    2.2使用return命令

    return命令来退出函数并返回特定的退出状态码。return命令允许指定一个整数值来定义函数的退出状态码,从而提供了一种简单的途径来编程设定函数退出状态码。

    $ cat test5
    #!/bin/bash
    # using the return command in a function
     function dbl {
       read -p "Enter a value: " value   
        echo "doubling the value"    
        return $[ $value * 2 ]
    }  
    dbl 
    echo "The new value is $?" 

    dbl函数会将$value变量中用户输入的值翻倍,然后用return命令返回结果。脚本用$?变量显示了该值。

    但当用这种方法从函数中返回值时,要小心了。记住下面两条技巧来避免问题:

    • 函数一结束就取返回值;
    • 退出状态码必须是0~255。

    例如我们运行一下:

    $ ./test5 
    Enter a value: 200 
    doubling the value 
    The new value is
    144

    2.3使用函数输出

    可以用下面这种方法来获得任何类型的函数输出,并将其保存到变量中:

    result=$(dbl)

     

    3在函数中使用变量

    3.1 向函数传递参数

    函数可以使用标准的参数环境变量来表示命令行上传给函数的参数。例如,函数名会在$0 变量中定义,函数命令行上的任何参数都会通过$1、$2等定义。也可以用特殊变量$#来判断传给函数的参数数目。

    在脚本中指定函数时,必须将参数和函数放在同一行,像这样:

    func1 $value1 10

    然后函数可以用参数环境变量来获得参数值。这里有个使用此方法向函数传值的例子。

    $ cat test6
    #!/bin/bash
    # passing parameters to a function
    function addem {
       if [ $# -eq 0 ] || [ $# -gt 2 ]    
       then
          echo -1
       elif [ $# -eq 1 ]    
       then
          echo $[ $1 + $1 ]   
       else
          echo $[ $1 + $2 ]    
       fi
    }  
    echo -n "Adding 10 and 15: " 
    value=$(addem 10 15) 
    echo $value 
    echo -n "Let's try adding just one number: " 
    value=$(addem 10) 
    echo $value 
    echo -n "Now trying adding no numbers: " 
    value=$(addem)
    echo $value 
    echo -n "Finally, try adding three numbers: " 
    value=$(addem 10 15 20) 
    echo $value 
    
    $ ./test6
    Adding 10 and 15: 25
    Let's try adding just one number: 20
    Now trying adding no numbers: -1
    Finally, try adding three numbers: -1

    由于函数使用特殊参数环境变量作为自己的参数值,因此它无法直接获取脚本在命令行中的参数值。

    3.2在函数中处理变量

    函数使用两种类型的变量:

    • 全局变量
    • 局部变量

    默认情况下,你在脚本中定义的任何变量都是全局变量。在函数外定义的变量可在函数内正常访问:

    $ cat test8
    #!/bin/bash
    # using a global variable to pass a value
     function dbl {
       value=$[ $value * 2 ]
    }  
    read -p "Enter a value: " value 
    dbl 
    echo "The new value is: $value"
    
    $ ./test8
    Enter a value: 450
    The new value is: 900

    函数内部使用的任何变量都可以被声明成局部变量。要实现这一点,只要在变量声明的前面加上local关键字就可以了。

    $ cat test9
    #!/bin/bash
    # demonstrating the local keyword
     function func1 { 
        local temp=$[ $value + 5 ]    
        result=$[ $temp * 2 ]
    }  
    temp=4 
    value=6  
    func1 
    echo "The result is $result" 
    if [ $temp -gt $value ] 
    then
        echo "temp is larger" 
    else
        echo "temp is smaller" 
    fi 
    
    $ ./test9 
    The result is 22 
    temp is smaller

     

    4数组变量和函数

    4.1 向函数传数组参数

    如果你试图将该数组变量作为函数参数,函数只会取数组变量的第一个值。要解决这个问题,你必须将该数组变量的值分解成单个的值,然后将这些值作为函数参数使用。在函数内部,可以将所有的参数重新组合成一个新的变量。下面是个具体的例子:

    $ cat test10
    #!/bin/bash
    # array variable to function test
     function testit {
         local newarray    
         newarray=($(echo "$@"))    
         echo "The new array value is: ${newarray[*]}"
    }  
    myarray=(1 2 3 4 5) 
    echo "The original array is ${myarray[*]}" 
    testit ${myarray[*]}
    
    $ ./test10
    The original array is 1 2 3 4 5
    The new array value is: 1 2 3 4 5

    该脚本用$myarray变量来保存所有的数组元素,然后将它们都放在函数的命令行上。该函数随后从命令行参数中重建数组变量。在函数内部,数组仍然可以像其他数组一样使用。

    $ cat test11
    #!/bin/bash
    # adding values in an array 
    function addarray {
        local sum=0    
        local newarray    
        newarray=($(echo "$@"))    
        for value in ${newarray[*]}    
        do 
              sum=$[ $sum + $value ]    
        done    
        echo $sum
    }  
    myarray=(1 2 3 4 5) 
    echo "The original array is: ${myarray[*]}" 
    result=$(addarray ${myarray[*]}) 
    echo "The result is $result"
    
    $ ./test11
    The original array is: 1 2 3 4 5
    The result is 15

    addarray函数会遍历所有的数组元素,将它们累加在一起。你可以在myarray数组变量中放置任意多的值,addarry函数会将它们都加起来。

    4.2从函数返回数组

    从函数里向shell脚本传回数组变量也用类似的方法。函数用echo语句来按正确顺序输出单个数组值,然后脚本再将它们重新放进一个新的数组变量中。

    #!/bin/bash
    function test {
    local array
    local newarray
    array=($(echo "$@"))
    sum=0
    for val in ${array[*]}
    do
    newarray[$sum]=$[$val*2]
    sum=$[$sum+1]
    done
    echo ${newarray[*]}
    }
    myarray=(1 2 3 4 5)
    echo "array: ${myarray[*]}"
    array=$(test ${myarray[*]})
    echo ${array[*]}      
    
    $ ./test12
    array: 1 2 3 4 5 
    2 4 6 8 10       

     

    5函数递归

    $ cat test13
    #!/bin/bash
    # using recursion
     function factorial { 
        if [ $1 -eq 1 ]    
        then 
              echo 1    
        else
               local temp=$[ $1 - 1 ]       
               local result=$(factorial $temp)       
               echo $[ $result * $1 ]    
        fi
    }   
    read -p "Enter value: " value 
    result=$(factorial $value) 
    echo "The factorial of $value is: $result"
    
    $ ./test13
    Enter value: 5
    The factorial of 5 is: 120

     

    6创建库

    使用函数可以在脚本中省去一些输入工作,这一点是显而易见的。但如果你碰巧要在多个脚本中使用同一段代码呢?显然,为了使用一次而在每个脚本中都定义同样的函数太过麻烦。有个方法能解决这个问题!bash shell允许创建函数库文件,然后在多个脚本中引用该库文件。

    第一步是创建一个包含脚本中所需函数的公用库文件

    $ cat myfuncs
    # my script functions
     function addem {
         echo $[ $1 + $2 ]
    }  
    function multem {
        echo $[ $1 * $2 ]
    }  
    function divem {
        if [ $2 -ne 0 ]    
        then 
              echo $[ $1 / $2 ]    
        else 
              echo -1    
        fi 
    }

    第二步是在用到这些函数的脚本文件中包含myfuncs库文件。(用source命令)

    使用函数库的关键在于source命令。source命令有个快捷的别名,称作点操作符。要在shell脚本中运行myfuncs 库文件,只需添加下面这行:

    . ./myfuncs

    所以,这里有个用myfuncs库文件创建脚本的例子:

    $ cat test14
    #!/bin/bash
    # using functions defined in a library file
    . ./myfuncs
     value1=10 
     value2=5 
     result1=$(addem $value1 $value2) 
     result2=$(multem $value1 $value2) 
     result3=$(divem $value1 $value2) 
     echo "The result of adding them is: $result1" 
     echo "The result of multiplying them is: $result2" 
     echo "The result of dividing them is: $result3"
    
    $ ./test14
    The result of adding them is: 15
    The result of multiplying them is: 50
    The result of dividing them is: 2

     

    7在命令行上使用函数

    7.1在命令行上创建函数

    因为shell会解释用户输入的命令,所以可以在命令行上直接定义一个函数。有两种方法。

    一种方法是采用单行方式定义函数。

    $ function divem { echo $[ $1 / $2 ];  }
    $ divem 100 5
    20

    当在命令行上定义函数时,你必须记得在每个命令后面加个分号,这样shell就能知道在哪里是命令的起止了。

    $ function divem { echo $[ $1 / $2 ];  }
    $ divem 100 5
    20

    另一种方法是采用多行方式来定义函数。在定义时,bash shell会使用次提示符来提示输入更多命令。用这种方法,你不用在每条命令的末尾放一个分号,只要按下回车键就行:

    $ function multem {
    > echo $[ $1 * $2 ]
    > }
    $ multem 2 5
    10

    在函数的尾部使用花括号,shell就会知道你已经完成了函数的定义。

    7.2.bashrc 文件中定义函数

    bash shell在每次启动时都会在主目录下查找这个文件,所以把函数写在.bashrc文件里面,每次启动一个新shell的时候,都会由shell重新载入。

    1. 直接定义函数

     

    $ cat .bashrc
    # .bashrc
    # Source global definitions
    if [ -r /etc/bashrc ]; then
            . /etc/bashrc
                 fi                                                         
     
    function addem {
       echo $[ $1 + $2 ]
     }                                                         
    $ cat .bashrc
    # .bashrc
    # Source global definitions
    if [ -r /etc/bashrc ]; then
            . /etc/bashrc
                                          

    2. 读取函数文件

    $ cat .bashrc
    # .bashrc
    # Source global definitions                                 
    if [ -r /etc/bashrc ]; then
            . /etc/bashrc
    fi
                                                                          
    . /home/rich/libraries/myfuncs

     

  • 相关阅读:
    Flask常用插件
    Mac使用Pyenv管理Python版本
    JS类似于C#中List的Where取FirstOrDefault写法
    MSSQL中Repalce函数处理长字符串时报异常的解决方案
    sqlcmd执行含中文等字符的sql脚本时报错解决方案
    使用7z程序CLI实现基础功能
    VBA中Selection.TypeText长度限制的替代写法
    .Net中Aspose组件调试技巧
    使用Foxit Reader实现批量打印以及一页多版设置技巧
    html2canvas中toDataURL方法返回值为:data,解决方案
  • 原文地址:https://www.cnblogs.com/ericz2j/p/12045667.html
Copyright © 2020-2023  润新知