shell--创建函数
知识体系: #创建函数 #使用参数 #共享函数 shell脚本代码可以封装在函数内,而函数可以在脚本任意处使用,由此减少大段代码的重复编写。 1、基本脚本函数 函数是被赋予名称的脚本代码块,可以在代码的任意位置使用。当需要调用代码块的时候,只需引用代码块被赋予的函数名即可。 1.1、创建函数 在bash shell脚本中创建函数可以使用两种方式: *关键字function,基本格式为: function name{ commands } *()方式: name() { commands } 下面就对这两种方式举例创建. 1.2、使用函数 如下采用上面创建函数的两种方式举例: [root ~]# chmod u+x 7.1test [root ~]# cat 7.1test #!/bin/bash function fun1 { echo "this is the first function" } fun1 fun2() { echo "this is the second function" } fun2 [root ~]# ./7.1test this is the first function this is the second function 这里头有两个函数名:fun1和fun2,对应两个函数执行后显示不同结果。 但是有点要注意的是必须先定义好函数,后才能调用,看个例子先: [root ~]# cat 7.1test #!/bin/bash function fun1 { echo "this is the first function" } fun1 fun2 fun2() { echo "this is the second function" } [root ~]# ./7.1test this is the first function ./7.1test: line 6: fun2: command not found 如上我把fun2放置在定义函数fun2之前就调用,shell是不会回头来执行的,所以对于函数fun2就报错了。 并且还要注意每个函数名必须唯一,如果重新定义函数,那么新定义的将取代原先的定义,看例子: [root ~]# cat 7.1test #!/bin/bash function fun1 { echo "this is the first function" } fun1 fun1() { echo "this is the second function" } fun1 [root ~]# ./7.1test this is the first function this is the second function 例子很简单,效果也看出来了,所以我们最好区分出函数名了。 2、返回值 bash shell将函数看成小型脚本,并以退出状态结束,我们可以通过$?查看三种不同的退出状态,这一点前面已经讲述过了。 2.1、默认退出状态 我们先来看一个例子: [root ~]# cat 7.2test #!/bin/bash function fun1 { echo "this is the first function" ls -l xx } fun1 echo "the exit status is :$?" [root ~]# chmod u+x 7.2test [root ~]# ./7.2test this is the first function ls: xx: 没有那个文件或目录 the exit status is :2 我们看到函数的退出状态为2,因为最后一条命令执行出错了。再来看看另外一种情况: [root ~]# cat 7.2test #!/bin/bash function fun1 { ls -l xx echo "this is the first function" } fun1 echo "the exit status is :$?" [root ~]# ./7.2test ls: xx: 没有那个文件或目录 this is the first function the exit status is :0 我把函数的两条命令调换位置执行,可以看到第一条报错了,然后退出状态值却是0。从这点我们发现函数的默认退出状态是不可靠的。 2.2、使用return命令 return命令可以使用单个整数值来定义函数退出状态,如下例子: [root ~]# cat 7.2test #!/bin/bash function cto { read -p "enter a value:" value echo "doubling the value" return $[ $value * 2 ] } cto echo "the new value is $?" [root ~]# ./7.2test enter a value:24 doubling the value the new value is 48 函数cto将变量$value中用户输入的值变成双倍后,使用命令return命令返回结果,然后用$?显示该结果。 2.3、使用函数输出 对于命令输出可以捕获并存放到shell变量中,函数的输出也可以捕获并放到shell变量中,看例子: [root ~]# chmod u+x 7.3test [root ~]# cat 7.3test #!/bin/bash ceo () { read -p "please input a value:" value echo $[ $value * 2 ] } result=`ceo` echo "the result is : $result" [root ~]# ./7.3test please input a value:13 the result is : 26 通过定义函数后,把函数输出赋予给变量,这里使用反引号。 3、在函数中使用变量 如下讲述shell脚本函数内外变量处理方法。 3.1、向函数传递参数 bash shell将函数作为小型脚本处理,函数可以使用标准参数环境变量来表示命令行传递给函数的参数,先看如下例子: [root ~]# cat 7.3test #!/bin/bash function cio { if [ $# -eq 0 ] || [ $# -gt 2 ] then echo -1 elif [ $# -eq 1 ] then echo $[ $1 + $1 ] else echo $[ $1 * $2 ] fi } echo "##############1##############" echo -n "adding 10 and 15 :" value=`cio 10 15` echo $value echo "##############2##############" echo -n "adding just one num of 10:" value=`cio 10` echo $value echo "##############3##############" echo -n "adding no num:" value=`cio` echo $value echo "##############4##############" echo -n "adding three num 10 20 30 :" value=`cio 10 20 30` echo $value [root ~]# ./7.3test ##############1############## adding 10 and 15 :150 ##############2############## adding just one num of 10:20 ##############3############## adding no num:-1 ##############4############## adding three num 10 20 30 :-1 先通过$#来判断参数个数,然后针对个数的不同执行不同的算术运算。通过把参数数目传递给函数去运算,把运行结果显示出来。 还有点注意的,因为函数为自己的参数值使用专用的参数环境变量,所以函数无法从脚本命令行直接访问脚本参数值,也就是说函数不识别运行脚本时后面附带的参数值。如果要调用,必须在使用函数时手工传递这些数据,我们来看个例子: [root ~]# cat 7.3test #!/bin/bash bad () { echo $[ $1 + $2 ] } if [ $# -eq 2 ] then value=`bad` echo "the result is : $value" else echo "please input two parameters" fi [root ~]# ./7.3test please input two parameters [root ~]# ./7.3test 1 2 ./7.3test: line 3: + : syntax error: operand expected (error token is " ") the result is : 之所以函数不认识1和2这两个$1、$2,就是因为函数使用的变量不同于脚本主代码的变量,所以我们必须在使用函数的使用手工附加,改成如下: [root ~]# cat 7.3test #!/bin/bash bad () { echo $[ $1 + $2 ] } if [ $# -eq 2 ] then value=`bad $1 $2` echo "the result is : $value" else echo "please input two parameters" fi [root ~]# ./7.3test please input two parameters [root ~]# ./7.3test 8 16 the result is : 24 哈哈,要的就是这个结果,所以value=`bad $1 $2`是关键语句!!! 3.2、在函数中处理变量 这里要提及一个作用域的概念,表示说变量的可见区域。函数内定义的变量和普通变量有不同的作用域,脚本外部定义的变量要覆盖函数内定义的变量。函数使用两个类型的变量: *全局变量 *局部变量 1》全局变量 全局变量是shell脚本内处处有效的变量,默认情况下脚本中定义的变量都是全局变量,而默认定义的变量在函数内部也可以正常访问的。例子: [root ~]# cat 7.3test #!/bin/bash fun () { value=$[ $value * 2 ] } read -p "please input the value:" value fun echo "the new value is : $value" [root ~]# ./7.3test please input the value:12 the new value is : 24 对于$value是在函数外部定义的,并且是在外部赋值,当调用给函数fun的时候,该变量在函数中也是有效的,所以这是全局变量的作用体现。 2》局部变量 对于函数内部使用的变量则是局部变量,而在声明变量的时候只要在前面多一个local关键字即可,先看下例子: [root ~]# cat 7.3test #!/bin/bash function cfo { local temp=$[ $value + 5 ] result=$[ $temp + 2 ] } temp=8 value=10 cfo echo "the result is $result" if [ $temp -gt $value ] then echo "temp is larger" else echo "temp is smaller" fi [root ~]# ./7.3test the result is 17 temp is smaller 对于这样的结果,可以分析如下:返回$result的结果是从函数中得到的,那么势必采用函数内部的temp变量,而函数内部的$temp变量赋予值后为15,则显示result的值为15+2=17。这一点没什么好质疑的!但是当temp和result进行大小比较的时候,就直接采用全局变量的值,而跟函数内部定义的temp无关了,这也是local定义内部函数的作用体现了。 这里我们顺便把变量的值取出来看看: [root ~]# cat 7.3test #!/bin/bash function cfo { local temp=$[ $value + 5 ] result=$[ $temp + 2 ] } temp=8 value=10 cfo echo "the result is $result" if [ $temp -gt $value ] then echo "temp is larger" echo "temp=$temp ; result=$result" else echo "temp is smaller" echo "temp=$temp ; result=$result" fi [root ~]# ./7.3test the result is 17 temp is smaller temp=8 ; result=17 我只是多加了两个echo "temp=$temp ; result=$result",就为了把temp和result这两个变量显示出来,我们看到,执行函数后,temp的值没变,因为函数中局部定义了temp,所以还是8;可是value的值通过函数运算后是有效生成的,所以附加后是17。 4、创建库 函数在单个脚本中有助于减少代码量,如果多个脚本碰巧使用相同的函数可以通过创建函数的库文件,然后再不同脚本中引用该库文件。所以这种方法,首先要创建公共库文件,如下: [root ~]# cat funcs function ceo { echo $[ $1 + $2 ] } function cfo { echo $[ $1 * $2 ] } 接下来把如上库文件调用进脚本文件。然后问题在于如果把这个库文件作为普通脚本文件运行,那么这些函数不会出现在脚本文件中,看如下例: [root ~]# chmod u+x funcs [root ~]# chmod u+x 7.41test [root ~]# chmod u+x 7.42test [root ~]# cat 7.41test #!/bin/bash ./funcs result=`ceo 12 24` echo "the result is $result" [root ~]# ./7.41test ./7.41test: line 3: ceo: command not found the result is 可以看到调用库文件失败了,问题就处在于通过./执行库函数是不可行的。 解决办法是通过点符号符在shell脚本中运行库文件脚本,即为source命令,其格式是: . ./xx 把例子修改如下: [root ~]# cat 7.41test #!/bin/bash . ./funcs result=`ceo 12 24` echo "the result is $result" [root ~]# cat 7.42test #!/bin/bash . ./funcs result=`cfo 12 5` echo "the result is $result" [root ~]# ./7.41test the result is 36 [root ~]# ./7.42test the result is 60 我们看到了满意的结果,关键在于通过. ./点符号符来使得脚本能以调用库文件的函数,这里头是把脚本文件和库文件放置于同一目录,所以为了确保路径问题的可靠性可使用绝对路径。 5、在命令行使用函数 有时候想直接在命令行下使用函数也是可以的,在命令行下使用函数有两种方法,分别如下: 1、将函数定义在一行命令中: [root ~]# function 51cto { echo $[ $1 / $2 ]; } [root ~]# 51cto 100 20 5 上面这种方法必须在命令的结尾处加分号,使得shell知道命令在哪里分开。 2、使用多行命令定义函数: [root ~]# function 51ceo { > echo $[ $1 * $2 ] > } [root ~]# 51ceo 3 8 24