数组和函数

作者:jicanmeng

时间:2016年05月19日


  1. 函数定义的两种格式
  2. 函数的返回值
  3. 函数的参数
  4. 在函数中定义变量
  5. 向函数传递数组和从函数返回数组

1. 函数定义的两种格式

有两种格式可以用来在bash shell脚本中创建函数。

  1. 第一种格式使用关键字function,后跟函数名,格式如下:
    function name {
        commands;
    }
  2. 第二种格式类似于c语言中的不带参数也没有返回值的函数,格式如下:
    name() {
        commands;
    }

要在脚本中使用函数,直接使用函数名就行了。

函数必须先定义,后使用。如果在函数定义前就调用函数,那么就会收到一个"command not found"的错误消息。

函数名必须是唯一的,否则会有问题。如果你重定义了函数,新定义会覆盖原来函数的定义,而不会产生任何错误消息。

2. 函数的返回值

bash shell会把函数当作小型脚本,运行结束时会返回一个退出状态吗。有3中不同的方法来为函数生成退出状态码。

  1. 默认情况下,函数的退出状态码是函数中最后一条命令的退出状态码。但是最后一条命令执行成功并不代表其它命令也执行成功。
  2. 使用return命令来退出函数并返回特定的退出状态码。使用这种方法的限制是:退出状态码必须在0~255之间。任何大于256的值都会返回一个错误值。举例如下:
  3. [jicanmeng@andy tmp]$ cat 1-return-value-using-return.sh
                        #!/bin/bash
    
                        func1() {
    	                        read -p "Enter a value: " value
    	                        echo "doubling the value"
    	                        return $[$value*2]
                        }
    
                        func1
                        echo "The new value is: $?"
                    [jicanmeng@andy tmp]$ ./1-return-value-using-return.sh
                        Enter a value: 20
                        The new value is: 40
                    [jicanmeng@andy tmp]$ 
  4. 正如可以将命令的输出保存到shell变量一样,也可以将函数的输出保存到shell变量中。可以用这种技术来获得任何类型的函数输出,并将其保存到变量中。函数返回值通过echo命令返回。例如下面的例子:
[jicanmeng@andy tmp]$ cat 2-return-value-using-echo.sh
                    #!/bin/bash

                    func1() {
	                        read -p "Enter a value: " value
	                        echo $[$value*2]
                    }

                    result=`func1`
                    echo "The new value is: $result"
                [jicanmeng@andy tmp]$ ./2-return-value-using-echo.sh
                    Enter a value: 200
                    The new value is: 400
                [jicanmeng@andy tmp]$ 

3. 函数的参数

在函数中,$0表示函数名。$1,$2等变量分别表示传递给函数的第一个参数,第二个参数等。$#表示参数个数。特别要注意,在bash shell脚本中的函数内部的$1,$2等变量表示传递给函数的参数,bash shell脚本中的函数外部的$1,$2等变量表示传递给shell脚本的参数,不要混淆。举例如下:

[jicanmeng@andy tmp]$ cat 3-function-parameter.sh
                    #!/bin/bash

                    func1() {
	                        if [ $# -ne 2 ]
	                        then
		                        echo -1
	                        else
		                        echo $[ $1 + $2 ]
	                        fi
                    }

                    echo -n "Adding 10 and 15: "
                    value=`func1 10 15`
                    echo $value
                [jicanmeng@andy tmp]$ ./3-function-parameter.sh
                    Adding 10 and 15: 25
                [jicanmeng@andy tmp]$ 

4. 在函数中定义变量

函数会用到两种类型的变量:全局变量和局部变量。

举例如下:
[jicanmeng@andy tmp]$ cat 4-function-variable.sh
                #!/bin/bash

                function db1 {
                        local temp=$[ $value + 5 ]
                        result=$[ $temp * 2 ]
                }

                temp=4
                value=6

                db1
                echo "The result is $result"
                if [ $temp -gt $value ]
                then
                        echo "temp is larger"
                else
                        echo "temp is smaller"
                fi
            [jicanmeng@andy tmp]$ ./4-function-variable.sh
                The result is 22
                temp is smaller
            [jicanmeng@andy tmp]$ 

5. 向函数传递数组和从函数返回数组

首先看一看bash shell中的数组的用法。数组是能够存储多个值的变量。值可按单个值或整个数组来引用。

定义一个数组变量非常简单,如下:
mytest=(one two three four five)

要引用一个单独的数组元素,你必须要使用索引值,并且索引值用方括号括起来。要显示整个数组变量,可用星号作为通配符放在索引值的位置。举例如下:

[jicanmeng@andy tmp]$ mytest=(one two three four five)
            [jicanmeng@andy tmp]$ echo $mytest[2]}
                three
            [jicanmeng@andy tmp]$ echo $mytest[*]}
                one two three four five
            [jicanmeng@andy tmp]$ echo $mytest
                one
            [jicanmeng@andy tmp]$ 

两点需要注意:1.数组的索引值从零开始,这点和c语言是一样的;2.使用$array的方式,只能得到数组中第一个元素的值

向函数传递数组参数,不能传递数组变量的值。因为上面提到,数组变量的值仅仅表示数组中第一个元素的值。举例如下:

[jicanmeng@andy tmp]$ cat 5-function-array.sh
                #!/bin/bash

                function testit {
	                    echo "The parameters are: $@"
	                    thisarray=$1
	                    echo "The received array is: ${thisarray[*]}"
                }

                myarray=(1 2 3 4 5)
                echo "The original array is ${myarray[*]}"
                testit $myarray
            [jicanmeng@andy tmp]$ ./5-function-array.sh
                The original array is 1 2 3 4 5
                The parameters are: 1
                The received array is: 1
            [jicanmeng@andy tmp]$ 

要解决这个问题,你必须将该数组变量的值分解成单个值然后将这些值作为函数参数使用。在函数内部,你可以将所有的参数重组到新的数组变量中。举例如下:

[jicanmeng@andy tmp]$ cat 6-function-array.sh
                #!/bin/bash

                function testit {
	                    local newarray
	                    newarray=(`echo "$@"`)
	                    echo "The received array is: ${newarray[*]}"
                }

                myarray=(1 2 3 4 5)
                echo "The original array is ${myarray[*]}"
                testit ${myarray[*]}
            [jicanmeng@andy tmp]$ ./6-function-array.sh
                The original array is 1 2 3 4 5
                The new array value is: 1 2 3 4 5
            [jicanmeng@andy tmp]$ 

下面看一看函数返回数组的情况。举例如下:

[jicanmeng@andy tmp]$ cat 7-function-array.sh
                #!/bin/bash

                function arraydblr {
	                    local origarray
	                    local newarray
	                    local elements
	                    local i
	                    origarray=(`echo "$@"`)
	                    newarray=(`echo "$@"`)
	                    elements=$#
	                    for (( i = 0; i < elements; i++  ))
	                    do
		                    newarray[$i]=$[ ${origarray[$i]} * 2 ]
	                    done
	                    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[*]}"
            [jicanmeng@andy tmp]$ ./7-function-array.sh
                The original array is 1 2 3 4 5
                The new array is: 2 4 6 8 10
            [jicanmeng@andy tmp]$ 

参考资料

  1. Lnux命令行与shell脚本编程大全
  2. 鸟哥的linux私房菜