• 创建函数


      在shell脚本编写中,通常有很多处使用相同的代码。如果这些代码比较短小,name通常并不费事。但是,如果有打断代码需要重写,则会让人厌烦,这个我们就需要使用函数来处理;

    1、基本脚本函数

      函数是被富裕名称的脚本代码块,可以在代码的任意位置重复使用。引用函数的过程,我们称之为调用;

      1.1、创建函数

        在bash shell脚本中创建函数可以使用两种格式:

    function name {  #name为唯一名称
        commands    #commands为组成函数功能的命令
    }

        另外一种格式

    name() {
    commands
    }

      1.2、使用函数

        相应的函数名需要在脚本中指定

    #!/bin/bash
    # using a function in a script
    
    function func1 {
        echo "This is an example of a funcation"
    }
    
    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"

        注意,不能在函数被定义之前去调用这个函数,会报错

    #!/bin/bash
    # using a function located in the middle of a script
    
    count=1
    echo "This line comes before the function definition"
    
    function func1 {
        echo "This is an example of a function"
    }
    
    while [ $count -le 5 ]
    do
        func1
        count=$[ $count + 1 ]
    done
    echo "This is the end of the loop"
    func2  #没有定义func2,所以这里会报错
    echo "Now this is the end of the script"

        函数的命名也需要注意,必须唯一。如果重新定义了函数,则新定义的函数就会覆盖原来的函数

    #!/bin/bash
    # testing using a duplicate function name
    
    function func1 {
        echo "This is first definition of the function name"
    }
    
    func1
    
    function func1 {  #新定义的函数就会覆盖原来的函数
        echo "This is a repeat of the same function name"
    }
    
    func1
    echo "This is the end of the script"

    2、返回值

      bash shell将函数看成小型的脚本,并以退出转态结束。函数退出转态有三种生成方式;

      2.1、默认退出状态

        函数的退出转态是函数的最后一条命令返回的退出状态 。可以$?来确定函数的退出状态;

    #!/bin/bash
    # testing the exit status of a function
    
    func1 () {
        echo "Trying to display a non-existend file"
        ls -l badfile
    }
    
    echo "testing the function:"
    func1
    echo "The exit status is: $?"

        这样可以知道函数执行转态为1,但是无法知道其他命令是否执行成功。

    #!/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 functiong:"
    func1
    echo "The exit status is: $?"

        因为函数中命令位置变换,则返回的函数转态值就是0了;所以这种方式来判断函数是不正确的;

      2.2、使用return命令

        所以,我们引入了return命令来指定函数转态。return命令可以使用单个整数值来定义函数退出转态,提供了一种通过编辑设置函数退出转态的简单方法;

    #!/bin/bash
    # using the return command in a function
    
    function db1 {
        read -p "Enter a value: " value
        echo "doubling the value"
        return $[ $value * 2 ]  #db1函数将变量$value中的用户输入值变为双倍后,通过return返回
    }
    
    db1
    echo "The new value is $?"

        注意两点:1、函数完成后尽快提取返回值;2、退出转态的取值范围是0-255;

      2.3、使用函数输出

        函数输出的结果可以给变量赋值:

        result=`db1`

        这样db1函数的值,就给了$result中

    #!/bin/bash
    # using the echo to return a value
    
    function db1 {
        read -p "Enter a value: " value
        echo $[ $value * 2 ]
    }
    
    result=`db1`
    echo "The new value is $result"

        这个函数使用echo语句显示计算结果,获取了db1的输出,而不是查看命令运行的状态结果;

    3、在函数中使用变量

      上一个函数中的$value就是函数变量使用的方法之一,在函数中要注意变量调用;

      3.1、向函数传递参数

        $1 $2 $# 如何传递给函数呢?

    #!/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

        由于函数为自己的参数值使用专用的参数环境变量,所以函数无法从脚本命令行直接范文脚本参数值。下面的例子就是一个错误的例子:

    #!/bin/bash
    # trying to access script parameters inside a function
    
    function badfunc1 {
        echo $[ $1 * $2 ]
    }
    
    if [ $# -eq 2 ]
    then 
        value=`badfunc1`
        echo "The result is $value"
    else
        echo "Usage: badtest1 a b"
    fi
    ./badtest1 10 15
    ./badtest1: * : syntax error: operand expected (error token is "*")

        该函数使用管道变量$1和$2,不同于脚本主代码的变量$1和$2.如果想在函数中使用这些值,那么必须在调用该函数时手动传递这些数据:

    #!/bin/bash
    # trying to access script parameters inside a function
    
    function func7 {
        echo $[ $1 * $2 ]
    }
    
    if [ $# -eq 2 ]
    then 
        value=`func7 $1 $2`  #一定要在函数中直接传递给变量;
        echo "The result is $value"
    else
        echo "Usage: badtest1 a b"
    fi

      3.2、在函数中处理变量

        函数中使用两种变量:1、全局变量;2、局部变量;

        1、全局变量

        shell脚本中全部地方都会生效

    #!/bin/bash
    # using a global variable to pass avalue
    
    function db1 {
        value=$[ $value * 2 ]
    }
    
    read -p "Enter a value: " value
    db1
    echo "The new value is: $value"

        $value在函数外部复制,同时在函数内部使用,依然生效。

        郑重做法要求程序员确切的清除函数中使用了那些变量,包括那些勇于计算值且不返回脚本的所有变量。

    #!/bin/bash
    # demonstrating a bad use of variables
    
    function func1 {
        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

        这种情况下,temp又在函数外部赋值,又在行数内部使用,所以结果可能会出人意料

        2、局部变量

        local 代表局部变量:local temp

        local temp=$[ $value + 5 ]

        local变量仅仅在函数内部使用;

    #!/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

        这样,func1内部使用变量$temp时,脚本主代码变量$temp的值不会受到映像

    4、数组变量与函数

      函数使用数组变量值需要一些技巧。

      4.1、向函数传递数组

        如果试图将数组变量作为单个参数传递,是无法正常工作的:

    #!/bin/bash
    # trying to pass an array variable
    
    function testit {
        echo "The parameters are: $@"
        this array=$1
        echo "The received array is ${thisarray[*]}"
    }
    
    myarray={1 2 3 4 5}
    echo "The original array is: ${myarray[*]}"
    testit $myarray

        这时候,函数只能提取数组的一个值。

        要解决这个问题,必须将数组变量拆分为单个元素,然后使用这些元素的值作为函数参数。

    #!/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[*]}

        这时候myarray[*]就能存放数组所有的值了;函数内部可以像使用其他素组一样使用这个数组;

    #!/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[*]}"
    arg1=`The original array is: ${myarray[*]}`
    result=`addarray $arg1`
    echo "The result is $result"

      4.2、从函数返回数组

        使用echo语句以恰当顺序输出数组元素之,然后脚本必须将这些数据重组为新数组变量;

    #!/bin/bash
    # returning an array value
    
    function arraydblr {
        local origarray
        local newarray
        local elements
        local i
        origarray=(`echo "$@"`)
        newarray=(`echo "$@"`)
        elements=$[ $# - 1 ]
        for (( i = 0; i <= $elements; i++ ))
        {
            newarray[$i]=[ ${origarray[$i]} * 2 ]
        }
        echo ${newarray[*]}
    }
    
    myarray=(1 2 3 4 5)
    echo "The original array is: ${myarray[*]}"
    arg1=`echo ${myarray[*]}`
    result=(`arraydblr $arg1`)
    echo "The new array is: ${result[*]}"
    ./test12
    The original array is: 1 2 3 4 5
    The new array is: 2 4 6 8 10

    5、函数递归

      递归调用函数是指函数调用自身进行求解。递归的一个经典案例是计算阶乘;

      5!=1*2*3*4*5=120

      这个就可以显示为:x!=x*(x-1)!

      这就可以以脚本的形式展现出来:

    function factorial {
        if [ $1 -eq 1 ]
        then
            echo 1
        else
            local temp=$[ $1 - 1 ]
            local result=`factorial $temp`
            echo $[ $result * $1 ]
        fi
    }

      该阶乘函数调用自身进行计算:

    #!/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"

    6、创建库

      多个脚本使用同样的函数,这时候我们就需要创建库文件才行;

    # 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
    }

      下一步将这个文件包含进需要调研的库函数中

      问题:如果从shell命令行界面运行myfuncs脚本,nameshell将打开一个新shell,并在该新shell中运行脚本。这将为新shell定义3个函数,但是当试图运行调用这些函数的另一个脚本时,库函数并不使用;

    #!/bin/bash
    # using a library file the wrong way
    ./myfuncs
    
    result=`addem 10 50`
    echo "The result is $result"

      使用函数库的关键命令时source命令。使用source命令再shell脚本内部运行库文件脚本。这样脚本就可以使用这些函数。

    #!/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"

    7、在命令行中使用函数

      函数可以使用在外面命令行中

      7.1、在命令行创建函数

        两种方法:

        1、将函数定义在一行命令中:

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

        $ divem 100 5

        在命令行中定义函数,每条命令后面必须用分号隔开;

        $ funtion doubleit { read -p "Enter value: " value; echo $[ $value * 2 ]; }

        $ doubleit

        2、使用多行命令定义函数。这样,bash shell使用次级命令提示符输入更多的命令

        $ function multem {

        > echo $[ $1 * $2 ]

        > }

        $ multem 2 5

        10

        $

      7.2、在.bashrc文件中定义函数

        在命令行下定义函数,一退出,就不能继续运行了。所以我们可以在.bashrc文件中来定义;

        1、直接定义函数

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

        2、提供函数文件

        正如shell脚本中的做法一样,可以使用source命令(点操作符),将库文件的函数包含进.bashrc脚本:

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

        确保库文件的准确路径,这样bash shell才能够找到库文件。再次启动shell之后,该库的所有函数将都能在命令行界面使用;

        更好的是,shell还将全部已定义函数传递给子shell进程。这样从shell会话运行的脚本,自定义函数随之可用。

    #!/bin/bash
    # using a function defined in the .bashrc file
    
    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"

        

  • 相关阅读:
    hdu3874
    spoj D-query
    hdu4348
    hdu4417
    hdu2665
    [LUOGU] P1057 传球游戏
    [CODEVS] 2193 数字三角形WW
    [CODEVS] 2189 数字三角形W
    [模板] 线段树
    [模板] 树状数组
  • 原文地址:https://www.cnblogs.com/BurnovBlog/p/10799057.html
Copyright © 2020-2023  润新知