Bash与”真正的”编程语言一样,Bash也有函数,虽然在某些实现方面稍有限制。一个函数就是一个子程序,用于实现一系列操作的代码块,它是完成特定任务的”黑盒子”。当存在重复代码的时候,或者当一个任务只需要轻微修改就被重复使用的时候,就需要考虑使用函数了。
函数定义
定义函数有两种方法:
function foo() {
#1
}
foo() {
#2 这种方法和c语言更加贴近,兼容性也更好。
}
需要注意的是函数的定义需要在使用之前。
函数参数
在调用函数的时候可以给函数传递参数。
如:
foo "bar"
如何在函数中使用这些参数呢,Bash中有特定的符号来表示各个参数。
$0
就是脚本文件自身的名字,$1
是第一个参数,$2
是第二个参数,$3
是第三个参数,以此类推。需要注意的是9以上的参数为了避免Bash解析错误,需要加上大括号或者双引号(使用${10}
,防止其被解析为${1}0
的形式)。$*
表示这个程式的所有参数。$#
表示这个程式的参数个数。
关于函数中变量的声明:如果变量用local来声明, 那么它就只能够在该变量被声明的代码块中可见。这个代码块就是局部”范围”。在一个函数中, 一个局部变量只有在函数代码块中才有意义。
函数的返回值
Bash函数中的return关键字会返回这个函数的退出状态码(shell中不区分变量的类型。但是shell会区分这个变量是整形还是字符串,其关键就是这个变量的值中是否只有数字。如果是整形则可以使用算数运算符对其进行计算。)。调用者可以通过读取$?
来获取函数的退出状态码变量($?
变量保存了一个命令,一个函数,或者是脚本本身的退出状态码)。我们可以通过设置全局变量或者使用命令替换。
下面这个简单的例子使用全局变量的方法进行了返回值的传递。
function foo() {
r="sometext"
}
foo
echo "$r"
这种做法虽然很简单方便,但是过多的定义全局变量将会导致这个程序的维护成本急剧增加。
更好的方法是在函数中使用local
变量,然后再结合命令替换的方式来把想传递的值传给调用者:
function foo() {
local r="sometext"
echo "$r"
}
result=$(foo) #等价于result=`foo`
echo "$result"
在这个例子中结果被输出到stdout
中,这样的话调用者就可以通过命令替换来获取返回值了。
还有一种方法可以进行值的返回,调用者可以将变量的名字传给函数,然后函数将返回值存储到这个名字的变量之中,这样调用者就可以直接通过访问这个变量来获取返回值了。
function myfunc()
{
local r=$1
local myresult='some text'
eval $r="'$myresult'"
}
myfunc result
echo $result
被一对双引号(” “)括起来的变量替换是不会被阻止的。所以双引号被称为部分引用,有时候又被称为”弱引用”。但是如果使用单引号的话(’ ‘), 那么变量替换就会被禁止了,变量名只会被解释成字面的意思,不会发生变量替换。所以单引号被称为全引用,有时候也被称为”强引用”。所以在以上的例子中要使用some text作为值的时候就不能使用”some text”,空格会引起脚本执行错误,只能使用’some text’。
在上面的例子中eval
会让shell先对$r="'$myresult'"
就行一次扫描和替换,变成result='some text'
。然后在正式运行函数的时候就会把’some text’赋值给result变量,这样调用者在来访问result变量就可以取得函数的返回值了。