03-Shell高级编程¶
Shell函数参数¶
和 C++、C#、Python 等大部分编程语言不同,Shell 中的函数在定义时不能指明参数,但是在调用时却可以传递参数。
函数参数是 Shell 位置参数的一种,在函数内部可以使用$n
来接收,例如,1 表示第一个参数,2 表示第二个参数,依次类推。
除了$n
,还有另外三个比较重要的变量:
$#
可以获取传递的参数的个数;$@
或者$*
可以一次性获取所有的参数(猛击《Shell *和@的区别》可以了解更多内容)。
n、#、@、* 都属于特殊变量,不了解的读者请转到《Shell特殊变量》。
【实例1】使用 $n 来接收函数参数。
#!/bin/bash
#定义函数
function show(){
echo "Tutorial: $1"
echo "URL: $2"
echo "Author: "$3
echo "Total $# parameters"
}
#调用函数
show C# http://c.biancheng.net/csharp/ Tom
运行结果: Tutorial: C# URL: http://c.biancheng.net/csharp/ Author: Tom Total 3 parameters
注意,第 7 行代码的写法有点不同,这里使用了 Shell 字符串拼接技巧。
【实例2】使用 $@ 来遍历函数参数。
定义一个函数,计算所有参数的和:
#!/bin/bash
function getsum(){
local sum=0
for n in $@
do
((sum+=n))
done
echo $sum
return 0
}
#调用函数并传递参数,最后将结果赋值给一个变量
total=$(getsum 10 20 55 15)
echo $total
#也可以将变量省略
echo $(getsum 10 20 55 15)
运行结果: 100 100
Shell函数返回值¶
在 C++、Java、C#、Python 等大部分编程语言中,返回值是指函数被调用之后,执行函数体中的代码所得到的结果,这个结果就通过 return 语句返回。
但是 Shell 中的返回值表示的是函数的退出状态:返回值为 0 表示函数执行成功了,返回值为非 0 表示函数执行失败(出错)了。if、while、for 等语句都是根据函数的退出状态来判断条件是否成立。
Shell 函数的返回值只能是一个介于 0~255 之间的整数,其中只有 0 表示成功,其它值都表示失败。
函数执行失败时,可以根据返回值(退出状态)来判断具体出现了什么错误,比如一个打开文件的函数,我们可以指定 1 表示文件不存在,2 表示文件没有读取权限,3 表示文件类型不对。
如果函数体中没有 return 语句,那么使用默认的退出状态,也就是最后一条命令的退出状态。如果这就是你想要的,那么更加严谨的写法为:
return $?
$?
是一个特殊变量,用来获取上一个命令的退出状态,或者上一个函数的返回值,请猛击《Shell $?》了解更多。
如何得到函数的处理结果?¶
有人可能会疑惑,既然 return 表示退出状态,那么该如何得到函数的处理结果呢?比如,我定义了一个函数,计算从 m 加到 n 的和,最终得到的结果该如何返回呢?
这个问题有两种解决方案:
- 一种是借助全局变量,将得到的结果赋值给全局变量;
- 一种是在函数内部使用 echo、printf 命令将结果输出,在函数外部使用
$()
或者````捕获结果。
下面我们具体来定义一个函数 getsum,计算从 m 加到 n 的和,并使用以上两种解决方案。
【实例1】将函数处理结果赋值给一个全局变量。
#!/bin/bash
sum=0 #全局变量
function getsum(){
for((i=$1; i<=$2; i++)); do
((sum+=i)) #改变全局变量
done
return $? #返回上一条命令的退出状态
}
read m
read n
if getsum $m $n; then
echo "The sum is $sum" #输出全局变量
else
echo "Error!"
fi
运行结果: 1 100 The sum is 5050
这种方案的弊端是:定义函数的同时还得额外定义一个全局变量,如果我们仅仅知道函数的名字,但是不知道全局变量的名字,那么也是无法获取结果的。
【实例2】在函数内部使用 echo 输出结果。
#!/bin/bash
function getsum(){
local sum=0 #局部变量
for((i=$1; i<=$2; i++)); do
((sum+=i))
done
echo $sum
return $?
}
read m
read n
total=$(getsum $m $n)
echo "The sum is $total"
#也可以省略 total 变量,直接写成下面的形式
#echo "The sum is "$(getsum $m $n)
运行结果: 1↙ 100↙ The sum is 5050
代码中总共执行了两次 echo 命令,但是却只输出一次,这是因为$()
捕获了第一个 echo 的输出结果,它并没有真正输出到终端上。除了$()
,你也可以使用````来捕获 echo 的输出结果,请猛击《Shell变量》了解两者的区别。
这种方案的弊端是:如果不使用$()
,而是直接调用函数,那么就会将结果直接输出到终端上,不过这貌似也无所谓,所以我推荐这种方案。
总起来说,虽然C语言、C++、Java 等其它编程语言中的返回值用起来更加方便,但是 Shell 中的返回值有它独特的用途,所以不要带着传统的编程思维来看待 Shell 函数的返回值。