2
3 factorial()
4 {
5 local i=$1
6 local l=$2
7
8 if[$i-eq 0 ]
9 then
10 eval${l}=1
11 rtn=1
12 else
13 factorial `expr $i- 1` ${l}
14 rtn=`expr $i \*$rtn `
15
16 local k=${!l}
17 eval${l}=`expr ${k}+ 1`
18 fi
19
20 return$rtn
21 }
22
23 if[-z $1]
24 then
25 echo "Need one parameter."
26 exit 1
27 fi
28
29 level=0
30 factorial $1 level
31
32 echo "The factorial of $1 is : $rtn"
33 echo " the function of factorial is invoked $level times." [root@localhost shell]# ./depth.sh 6
The factorial of 6 is : 720
the function of factorial is invoked 7 times.
在上面我们曾经介绍过,为了解决变量作用域和函数返回值的问题,在递归函数中我们使用 local 声明局部变量,并采用全局变量来传递返回值。但是随着调用关系变得更加复杂,全局变量的值有可能在其他地方被错误地修改。实际上,使用局部变量也存在一个问题,下面让我们来看一下清单 11 中给出的例子。
清单11. 查找字符串在文件中是否存在,并计算所在行数和出现次数
[root@localhost shell]# cat -n getline1.sh
1 #!/bin/bash
2
3 GetLine()
4 {
5 string=$1
6 file=$2
7
8 line=`grep-n $string$file`
9 if[$?-eq 0 ]
10 then
11 printf"$string is found as the %drd line in $file \n" `echo $line \ | cut -f1 -d:`
12 num=`grep$string$file| wc -l`
13 rtn=0
14 else
15 printf"$string is not found in $file \n"
16 num=0
17 rtn=1
18 fi
19
20 return$rtn;
21 }
22
23 if[!-f testfile.$$]
24 then
25 cat >> testfile.$$<<EOF
26 first line .
27 second line ..
28 third line ...
29 EOF
30 fi
31
32 num=0
33 rtn=0
34 for i in "second""six""line"
35 do
36 echo
37 GetLine $i testfile.$$
38 echo "return value: $rtn"
39
40 if[$num-gt 0 ]
41 then
42 echo "$num occurences found totally."
43 fi
44 done [root@localhost shell]# ./getline1.sh
second is found as the 2rd line in testfile.4280 return value: 0
1 occurences found totally.
six is not found in testfile.4280 return value: 1
line is found as the 1rd line in testfile.4280 return value: 0
3 occurences found totally. [root@localhost shell]#
2
3 GetLine()
4 {
5 local string=$1
6 local file=$2
7
8 local line=`grep-n $string$file`
9 if[$?-eq 0 ]
10 then
11 printf"$string is found as the %drd line in $file \n" `echo $line \ | cut -f1 -d:`
12 num=`grep$string$file| wc -l`
13 rtn=0
14 else
15 printf"$string is not found in $file \n"
16 num=0
17 rtn=1
18 fi
19
20 return$rtn;
21 }
22
23 if[!-f testfile.$$]
24 then
25 cat >> testfile.$$<<EOF
26 first line .
27 second line ..
28 third line ...
29 EOF
30 fi
31
32 num=0
33 rtn=0
34 for i in "second""six""line"
35 do
36 echo
37 GetLine $i testfile.$$
38 echo "return value: $rtn"
39
40 if[$num-gt 0 ]
41 then
42 echo "$num occurences found totally."
43 fi
44 done [root@localhost shell]# ./getline2.sh
second is found as the 2rd line in testfile.4300 return value: 0
1 occurences found totally.
six is found as the 0rd line in testfile.4300 return value: 0
line is found as the 1rd line in testfile.4300 return value: 0
3 occurences found totally.
清单 12 的运行结果显示,在文件中搜索 six 关键字时的结果是错误的,调试会发现,问题的原因在于:第 8 行使用 local 将 line 声明为局部变量,并将 grep 命令的执行结果赋值给 line 变量。然而不论 grep 是否成功在文件中找到匹配项(grep 程序找到匹配项返回值为 0,否则返回值为 1),第 9 行中 $? 的值总是 0。实际上,第 8 行相当于执行了两条语句:第一条语句使用 grep 在文件中查找匹配项,第二条语句将 grep 命令的结果赋值给变量 line,并设定其作用域只对于本函数及其子进程可见。因此第 9 行命令中 $? 的值实际上是执行 local 命令的返回值,不管 grep 命令的结果如何,它总是 0。
要解决这个问题,可以将第 8 行的命令拆分开,首先使用单独一行将变量 line 声明为 local的,然后再执行这条 grep 命令,并将结果赋值给变量 line(此时前面不能加上 local)。