由于函数使用位置变量访问函数参数,因此无法直接获取脚本的命令行参数。下面的例子无
法成功运行:
$ cat badtest1
#!/bin/bash # trying to access script parameters inside a function function badfunc1 {echo $[$1*$2]}if[ $# -eq 2 ]
then
value=$(badfunc1)echo"The result is $value"elseecho"Usage: badtest1 a b"fi
$
$ ./badtest1
Usage: badtest1 a b
$ ./badtest1 1015./badtest1:*: syntax error: operand expected(error token is "*
")
The result is
$
尽管函数使用了$1 变量和$2 变量,但它们和脚本主体中的$1 变量和$2 变量不是一回事。
正确调用命令行参数方法
要在函数中使用脚本的命令行参数,必须在调用函数时手动将其传入:
$ cat test7
#!/bin/bash # trying to access script parameters inside a function function func7 {echo $[$1*$2]}if[ $# -eq 2 ]
then
value=$(func7$1$2)echo"The result is $value"elseecho"Usage: badtest1 a b"fi
$
$ ./test7
Usage: badtest1 a b
$ ./test7 1015
The result is 150
$
在将$1 变量和$2 变量传给函数后,它们就能跟其他变量一样,可供函数使用了。
全局变量是在 shell 脚本内任何地方都有效的变量。如果在脚本的主体部分定义了一个全局
变量,那么就可以在函数内读取它的值。类似地,如果在函数内定义了一个全局变量,那么也可
以在脚本的主体部分读取它的值。
在默认情况下,在脚本中定义的任何变量都是全局变量。在函数外定义的变量可在函数内正
常访问:
$ cat test8
#!/bin/bash # using a global variable to pass a value function dbl {
value=$[$value*2]}
read -p "Enter a value: " value
dbl
echo"The new value is: $value"
$
$ ./test8
Enter a value:450
The newvalue is:900
$
$value 变量在函数外定义并被赋值。当 dbl 函数被调用时,该变量及其值在函数中依然有
效。如果变量在函数内被赋予了新值,那么在脚本中引用该变量时,新值仍可用。
但这种情况其实很危险,尤其是想在不同的 shell 脚本中使用函数的时候,因为这要求你清
清楚楚地知道函数中具体使用了哪些变量,包括那些用来计算非返回值的变量。这里有个例子可
以说明事情是如何被搞砸的:
$ cat badtest2
#!/bin/bash# demonstrating a bad use of variablesfunction func1 {
temp=$[$value+5]
result=$[$temp*2]}
temp=4
value=6
func1
echo"The result is $result"if[$temp-gt$value]
then
echo"temp is larger"elseecho"temp is smaller"fi
$
$ ./badtest2
The result is 22
temp is larger
$
由于函数中用到了$temp 变量,因此它的值在脚本中使用时受到了影响,产生了意想不到
的后果。有一种简单的方法可以解决函数中的这个问题,那就是使用局部变量。
局部变量
无须在函数中使用全局变量,任何在函数内部使用的变量都可以被声明为局部变量。为此,
只需在变量声明之前加上 local 关键字即可:
local temp
也可以在变量赋值语句中使用 local 关键字:
local temp=$[$value+5]
local 关键字保证了变量仅在该函数中有效。如果函数之外有同名变量,那么 shell 会保持
这两个变量的值互不干扰。这意味着你可以轻松地将函数变量和脚本变量分离开,只共享需要共
享的变量:
$ cat test9
#!/bin/bash# demonstrating the local keywordfunction func1 {
local temp=$[$value+5]
result=$[$temp*2]}
temp=4
value=6
func1
echo"The result is $result"if[$temp-gt$value]
then
echo"temp is larger"elseecho"temp is smaller"fi
$
$ ./test9
The result is 22
temp is smaller
$
现在,当你在 func1 函数中使用$temp 变量时,该变量的值不会影响到脚本主体中赋给
$temp 变量的值。
函数递归
局部函数变量的一个特性是自成体系(self-containment)。除了获取函数参数,自成体系的
函数不需要使用任何外部资源。
这个特性使得函数可以递归地调用,也就是说函数可以调用自己来得到结果。递归函数通常
有一个最终可以迭代到的基准值。许多高级数学算法通过递归对复杂的方程进行逐级规约,直到
基准值。
递归算法的经典例子是计算阶乘。一个数的阶乘是该数之前的所有数乘以该数的值。
阶乘函数用其自身计算阶乘的值:
$ cat test13
#!/bin/bash # using recursion function factorial {if[$1-eq 1]
then
echo1else
local temp=$[$1-1]
local result=$(factorial$temp)echo $[$result*$1]
fi
}
read -p "Enter value: " value
result=$(factorial$value)echo"The factorial of $value is: $result"
$
$ ./test13
Enter value:5
The factorial of 5 is:120