Poem 2013-09-14
shell script 作为一种结构化的编程语言,允许在 script 中定义和使用函数。函数是将一组命令集或者语句形成一个可复用的代码块。
1. 函数定义
shell 函数和其他语言的函数一样,都需要先定义才能使用。
语法格式如下:
function_name () { ... }
或者
function_name () { ... }
或者
function function_name [()] { ... }
或者
function function_name [()] { ... }
1 function_name 是函数名;花括号之间的内容是函数体(命令或者语句的集合)。
2 命令 function 是可选的。如果 function 存在,则后面的圆括号是可选的;如果省略 function,则后面的圆括号不能省略。
3 左花括号也可以写在和函数名的同一行。
2. 函数调用
shell 函数调用的方式和 shell 命令是一样的,可以把函数当作命令来使用。
语法格式如下:
function_name [arguments ...]
1 函数和参数之间、参数和参数之间使用空格分隔。
2 函数和命令在使用上基本相同,同样都可以使用 shell 的命令替换功能($()、``)。
示例 1
test.sh 文件的内容如下
ERROR_CODE=255 max_value () { if [ $# != 2 ]; then echo invalid argument return $ERROR_CODE fi echo max number is $(($1 > $2 ? $1 : $2)) } max_value 23 12
执行结果如下
malihou@ubuntu:~$ malihou@ubuntu:~$ ./test.sh max number is 23 malihou@ubuntu:~$
示例 2
test.sh 文件的内容如下
version() { echo "GNU bash, version 4.2.24(1)" } bash_version=`version` echo $bash_version
执行结果如下
malihou@ubuntu:~$ malihou@ubuntu:~$ ./test.sh GNU bash, version 4.2.24(1) malihou@ubuntu:~$
3. 函数名
shell 函数的函数名保存在数组变量 FUNCNAME 中。这个变量只能使用在函数中,使用在其他地方将无效。
示例 3
test.sh 文件的内容如下
func3 () { echo $FUNCNAME : ${FUNCNAME[@]} } func2 () { func3 echo $FUNCNAME : ${FUNCNAME[@]} } func1 () { func2 echo $FUNCNAME : ${FUNCNAME[@]} } func1
执行结果如下
malihou@ubuntu:~$ malihou@ubuntu:~$ ./test.sh func3 : func3 func2 func1 main func2 : func2 func1 main func1 : func1 main malihou@ubuntu:~$
4. 函数参数
1 shell 允许在调用函数的时候使用任意个参数,函数以位置来引用传递过来的参数。因此参数在函数内部会成为位置参数,其使用方法和 script 中相同。
2 shell 会保存调用函数前的位置参数,以便在函数内部重新给位置参数赋值。在函数调用完成后,位置参数会还原回函数调用前的值。传递给函数的参数和传递给 script 的命令行参数不会被混淆。
3 位置参数可以使用在 script 和函数内部。
4 和其它语言不同的是,shell 将传递给函数的参数都解释为字符串,在这之前会对参数进行 ~ 展开、参数和变量展开、算术展开、命令替代操作。
示例 4
test.sh 文件的内容如下
num1=12 num2=23 num3=34 test_positonal_parameter () { echo \$#=$# \$@="$@" } echo \$#=$# \$1=$1 \$2=$2 test_positonal_parameter $num1 $num2 $num3 45 echo \$#=$# \$1=$1 \$2=$2
执行结果如下
malihou@ubuntu:~$ malihou@ubuntu:~$ ./test.sh 1 2 $#=2 $1=1 $2=2 $#=4 $@=12 23 34 45 $#=2 $1=1 $2=2 malihou@ubuntu:~$
5. 函数局部变量
1 在函数内部定义的变量在默认情况下都是全局变量(没有使用命令 local 声明),这些全局的变量在函数调用之后才可以在函数外部使用。
2 如果变量在使用命令 local 声明后,就成为局部变量,其只能在函数内部及其子函数内被使用。
3 在函数调用之后,所有在函数内定义且没有使用命令 local 声明的变量都可以在函数外部可见。
示例 5
test.sh 文件的内容如下
test_variable () { var1=global local var2=local echo var1=$var1 var2=$var2 } echo var1=$var1 var2=$var2 test_variable echo var1=$var1 var2=$var2
执行结果如下
malihou@ubuntu:~$ malihou@ubuntu:~$ ./test.sh var1= var2= var1=global var2=local var1=global var2= malihou@ubuntu:~$
局部变量可以递归。因此在实现函数递归调用时,必须使用局部变量。但是太多层的递归会消耗大量的内存,因此递归调用需谨慎使用。
使用函数递归输出杨辉三角(pascal's triangle)。
示例 6
test.sh 文件的内容如下
if [ $# -eq 0 ] then echo invalid argument exit fi recursive () { local i=$1 local j=$2 local m local n if [ $j -eq 1 ] || [ $j -eq $i ] then return 1 fi recursive $((i-1)) $((j-1)) m=$? recursive $((i-1)) $((j)) n=$? return $((m + n)) } for i in `eval echo {1..$1}` do for j in `eval echo {1..$i}` do recursive $((i)) $((j)) result=$? if [ $j -eq $i ] then echo "$result" else echo -n "$result " fi done done
执行结果如下
malihou@ubuntu:~$ malihou@ubuntu:~$ ./test.sh 6 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1 malihou@ubuntu:~$
6. 函数返回值
1 shell 函数是有返回值的。命令 return 可选的带一个整数参数(不带参数的 return 等同于 return $?),这个整数值会返回给调用此函数的 script。同时这个整数值会赋给变量 $?。
2 如果在函数中不使用 return 返回或者使用不带参数的 return,则将返回函数最后一条语句的退出状态的值(exit status = $?)。
3 退出状态 $? 的值是有限制的,其值的范围为 0 <= $? <= 255。如果超出这个范围,shell 会对 $? 的值进行取模运算($? % 256)。
4 命令 return 只能使用在 shell 函数中,不能使用在其他地方。
示例 7
test.sh 文件的内容如下
test_return () { return $1 } test_return 128 echo \$?=$? test_return 255 echo \$?=$? test_return 258 echo \$?=$?
执行结果如下:
malihou@ubuntu:~$ malihou@ubuntu:~$ ./test.sh $?=128 $?=255 $?=2 malihou@ubuntu:~$
如果想在函数中返回一个大的整数值,则需要通过在函数中将返回值传递给一个全局变量来实现。或者是让函数将返回值输出到标准输出,然后再通过命令替代的方式捕获这个返回值。
示例 8
test.sh 文件的内容如下
return_value=0 if [ $# -lt 4 ] then echo invalid argument exit fi max_value1 () { return_value=$(($1 > $2 ? $1 : $2)) } max_value2 () { echo $(($1 > $2 ? $1 : $2)) } max_value1 $1 $2 echo max value is $return_value echo max value is `max_value2 $3 $4`
执行结果如下
malihou@ubuntu:~$ malihou@ubuntu:~$ ./test.sh 1000 1234 2000 2234 max value is 1234 max value is 2234 malihou@ubuntu:~$
7. 创建函数文件
和 c 语言的库函数一样,在 shell 中可以把一些经常使用的函数放在一起,并保存在函数文件中。当函数文件加载到 shell 后,就可以在命令行或者 script 中调用函数文件中的函数。
1 函数文件的文件名可以任意选取。
2 使用命令 set 查看所有定义的变量和函数。
3 使用命令 unset 删除变量和函数。
8. 加载函数文件
加载函数文件时,需要使用命令 source file 和 . file 的方式。
示例 9
shell_function.sh 文件的内容如下
echo "Usage : compare two number" max_value () { return $(($1 > $2 ? $1 : $2)) }
加载函数文件,执行结果如下
malihou@ubuntu:~$ malihou@ubuntu:~$ source shell_function.sh Usage : compare two number malihou@ubuntu:~$
将函数加载到 shell 后,执行结果如下
malihou@ubuntu:~$ malihou@ubuntu:~$ max_value 23 45 malihou@ubuntu:~$ malihou@ubuntu:~$ echo $? 45 malihou@ubuntu:~$
如果需要在其他 script 中使用函数文件,则首先需要在 script 的开头使用 source file 和 . file 将函数文件加载到当前 script 中,才可以使用这些函数。
示例 10
test.sh 文件的内容如下
source shell_function.sh max_value 123 23 echo the max value is : $?
执行结果如下
malihou@ubuntu:~$ malihou@ubuntu:~$ ./test.sh Usage : compare two number the max value is : 123 malihou@ubuntu:~$
来源: http://malihou2008.blog.163.com/blog/static/211820045201210462849297/