简介
函数是被赋予特定名字的代码块,可以再脚本中任意位置调用,合理地提取函数可以减少脚本代码的重复量,同时也方便去构建代码逻辑结构。在Bash Shell中,函数可以被理解为轻量级的脚本,执行函数类似与运行一个脚本,可以传递参数,也有返回值。
基本使用
创建函数
创建函数有两种方式,确切说是两种创建函数的语法,第一种是:
1 | function name { |
第二种是:
1 | name() { |
上面的两种方式是等效的。
调用和返回
创建函数后,调用函数和运行命令类似:
1 | name [arg] |
上述为调用name函数,arg是传递给函数的参数。调用函数之后,将会以此执行commands中的命令,默认情况下,函数将以最后一个命令的退出状态码退出,该码保存在$?中,需要注意的是$?保存的是最新执行命令的退出状态码,因此如果需要该码一定要及时地读取和处理,以防被后续命令的退出状态码覆盖。
return
利用函数的默认退出状态码,很不方便去获取函数执行完成后的状态,比如中途有个地方执行出错了,我对此一无所知。Bash Shell提供了return命令用来控制函数何时退出以及返回什么状态码(范围是0~255)。例如:
1 | name() { |
返回任意内容
上述的return命令虽然可以控制函数的终止和退出状态码,但是就是上面所述,很明显有着很大的限制。除了return外,我们还有另外一种方式来返回数据,也就是利用函数中的输出,在调用函数的时候可以利用一个变量来捕获函数中的输出,从而达到返回的效果。例如:
1 | function name { |
上述利用msg变量捕获了name函数的输出,再结合return命令,可以很好的对函数进行控制。需要注意的是,msg会捕获函数中的基本所有输出,除了一些命令如read设置的提示输入字符,所以使用的时候需要留心。
了解了后面讲述的作用域之后,很明显还可以用全局变量来获取函数中的数据当作返回值,但是这样子一定要相当留心。
作用域
和很多变成语言一样,变量通常都有作用域,即变量在规定的作用域才会有意义,作用域定义了变量的可见区域。函数中分有全局变量和局部变量,全局变量在脚本中全局可见,而局部变量则只在其定义的函数中可见。
在脚本函数外定义的变量就是全局变量,在任何地方都可以访问到。而在函数内部定义的变量,则是局部变量,只能函数内部可见。例如:
全局变量
1 | func() { |
局部变量
1 | func() { |
可以看出,函数内部可以访问全局变量,而函数内部的变量外部无法访问。
local命令
local命令可以函数内指定某个变量为局部变量,即便该变量和全局变量同名。例如:
1 | func() { |
函数参数
和一开始讲到那样,函数就像是轻量级的命令,同样的,函数传递参数和命令传递参数是一样的,就是在函数内获取参数,也是同样的获取方法,用一些特殊变量来保存这些参数。例如:
1 | func() { |
可以看见,除了$0还是表示脚本名称外,其他的都表示与函数传入参数相关的信息了。如果在函数中使用shift命令,那么将对函数的传入参数进行移位。
导入外部脚本
通常的,对于比较复杂的脚本,我们可以将脚本拆分为多个,然后将其导入到其他脚本中,以方便代码组织。很常用的一种就是创建单独的库文件,里面放一些通用的函数。主要难点在于如何将一个脚本导入另一个脚本中。这里要用到的就是source命令,也就是所谓的点操作符。我们可以在一个脚本中使用source filename导入其他脚本,之所所称为点操作符,因为source filename和. filename是等效的。加入有脚本文件名为myshelllib如下:
1 | function test { |
下面同一目录下的test.sh需要用上面的函数,则test.sh可以如下引入库中的函数:
1 | source myshelllib #或者:. myshelllib |