一.shell中函数的基本用法
1.函数的语法格式
常用的函数的语法格式有两种:
<1>语法一:
function 函数名() {
函数体
return n #可有可无
}
<2>语法二:
函数名() {
函数体
return n #可有可无
}
说明:(1)函数名是用字母,下划线和数字构成的,以字母或下划线开头,不能以数字开头。一般以函数功能命名。
(2)我们一般使用语法一。
2.调用函数
调用函数时,直接利用函数名,不用带圆括号,就像一般命令那样使用。
案例:用两种格式定义函数,并调用函数
3.引用函数
每次引用函数时,bash会重新回到函数的定义。
案例:
4.函数定义的位置要求
函数不一定要在最开始定义,但是如果函数在定义前就使用,回报错。
案例:函数调用要在函数定义之后
注意:如果在函数定义之前使用函数,会收到一条错误消息
5.函数名唯一性的要求
函数名必须是唯一的,如果重新定义了函数,新的函数会覆盖旧的。
案例:函数出现重名时,以最新的函数为准,后续的函数调用都会使用新定义的函数
二.shell中函数的返回值
bash shell会把函数当成一个小型的脚本,当函数运行结束时会返回一个退出状态码。
可以使用三种方式去获取退出状态码。
1.默认退出状态码
- 获取默认退出状态码,即在函数执行完成后,立即获得$?的值,此时获得的是函数最后一条命令的退出状态码。成功为0,不成功为非0
- 但是默认退出状态码,无法知道函数其他命令是否成功执行。
案例1:测试函数返回为不成功的案例
案例2:测试函数返回为成功的案例
2.使用return命令
- 使用return命令可以返回特定的退出状态码,允许指定一个整数来定义函数的退出状态码。
- (退出状态的取值范围是0到255,$?是最近已执行命令的退出状态)。
- 若大于255,对256取余。
案例:
1 #!/bin/bash
2 function db1() {
3 read -p "Enter a value:" value
4 echo "doubling the value"
5 return $[$value*2]
6 }
7 db1
8 echo "The new value is:" $?
>>>db1函数会将变量value的输入值翻倍并返回结果,但是返回值在0~255之间,若大于255,对256取余
3.使用函数输出(这样就能很好的利用输出结果)
将函数的输出保存在shell变量中,可以获得任何类型的函数输出。
案例:
说明
>>>函数func用echo语句显示计算结果
>>>result=`func`,这个命令将func函数的输出赋给$result变量,而不是查看退出状态码。
三.shell中函数的传参
bash shell会将函数当成一个小型的shell脚本来对待:
这就意味着:我们可以像在命令行执行脚本时通过位置参数的方式将参数传递给函数。
1.基本格式:
function func() {
$1
$2
}
func parameter1 parameter2
说明:传入$1的值是获取parameter1的值,传入$2的值是获取parameter2的值,而不是获取命令行参数
2.案例
<1>案例1:
说明:要区别第一个$1,$2和第二个$1,$2 ,
第一个$1,$2是脚本的位置参数,它获取的是命令行的位置参数
第二个$1,$2是函数的位置参数,它获取的是紧跟在调用函数时,函数名后面的位置参数,即此脚本的最后一条命令
<2>案例2:针对案例1,要想使得第一个$1,$2和第二个$1,$2相同,又该如何做呢?
错误做法:
说明:函数不能直接从命令行上获取脚本的参数值
正确做法1:将变量$1和$2定义为全局变量
正确做法2:给函数传递参数$1和$2
<3>案例3:
错误做法:
正确做法1:将变量$1和$2定义为全局变量
正确做法2:给函数传递参数$1和$2
说明:可以向函数中传递参数,函数名会在$0变量中定义,函数命令行上的任何参数都会通过$1,$2定义,$#用来判断传给函数的参数的个数。
<4>案例4:
如果命令行输入的参数个数为0,则输出-1;如果输入的参数个数为1,则输出值为该参数的值*2;如果输入的参数个数为2,则输出值为这两个参数的和;如果是别的,则输出错误。
错误做法:
正确做法1:将变量$1,$2和$#定义为全局变量
错误做法2:给函数传递参数$1,$2
这里需要注意的是$#不能作为参数,传递给函数。$#是参数的个数。
错误的原因:在运行result函数时,$#在result函数中,而result函数中并没有传入参数,所以$#一直为0,所以输出结果一直为0。
正确做法二:(但是该做法不好,有缺陷)
这里值得注意的是:因为往result函数中传入的参数只有两个,$1和$2,所以$#判断的参数的个数最多为2个,所以输出不了error的情况。因为,并不知道,用户会输入几个参数,所以,这里result函数中传入的参数并不确定,所以,该方法是有缺陷的。
四.在函数中处理变量
>>>变量处理关键点:变量的作用域问题,作用域即为在什么情况下变量可见
>>>在函数中,变量可分为两类:全局变量和局部变量
全局变量:
在shell脚本中任何地方都有效的变量(但是shell脚本结束后,变量也会失效,这点与系统的全局变量要区分)
在脚本的主体部分定义的全局变量,函数中可以调用
函数中定义的全局变量,在脚本中主体部分可以读取
默认情况下,在脚本中定义的任何变量都是全局变量
局部变量:
函数内部使用变量,在声明前加上local关键词即可成为局部变量
变量只限于在函数中使用 (当需要在函数内部使用变量时,使用局部变量避免与外部变量弄混)
案例1:
案例2:
案例3:
这里值的注意的是:当脚本主体定义的全局变量与函数中定义的局部变量同名时,在函数内部使用的是局部变量,在脚本主体使用的是全局变量。
五.shell中的函数递归
bash也支持递归函数(能够调用自身的函数)
案例:交互式输入一个数字,编写脚本实现功能:计算该数字的阶乘。
方法1:使用for循环
方法二:利用while循环
方法三:利用函数的递归