SAKA'S BLOG

shell函数

shell中的函数

这个系列的文章主要是最近研究安卓源码,发现好多shell和makefile的命令不懂,只能硬着头皮学一波。

1. 函数的定义

shell中定义函数的方式如下:

1
2
3
4
5
function function_name(){
command1
command2
[return]
}

写一个最简单的例子,新建文件function.sh,内容如下:

1
2
3
4
#!/bin/bash
function foo(){
echo "foo"
}

这就是一个完整的函数.function关键字可有可无,一般建议写出。

2. 函数的调用
1
function_name [param...]

直接执行函数名称即可,后边可以跟一些参数.
现在我们要执行foo函数,只需要在文件末尾添加foo即可.,然后执行source function.sh,可以看到如下输出:

1
foo

传入的参数可以在脚本中通过$<index> 的形式来获取.注意0是由调用函数的程序名称占用的,而index是从1开始的,以任意个空格来区分.假如传入的参数少于索引,则索引位置为空.
现在将程序修改如下:

1
2
3
4
5
6
7
8
9
10
11
#!/bin/bash
function foo(){
echo "foo praam 0=$0"
echo "foo param 1=$1"
echo "foo param 2=$2"
echo "foo param 3=$3"
echo "all parma=$@"
echo "all param=$*“
echo "count=$#"
}
foo hello world

然后执行source function命令,输出如下:

1
2
3
4
5
6
7
foo param 0=/bin/bash
foo param 1=hello
foo param 2=world
foo param 3=
all parma=hello world
all param=hello world
count=2

上边关于参数系统提供了一些方法:
$@表示全部的参数,格式是”$1” “$2”…
$也表示全部的参数,格式是”$1 $2 …”
实际中用$@比较多,因为他将参数全部分开了,是数组形式,而$
是将所有的参数汇总为了一个参数。
$#表示参数的个数

3. 函数的返回值

shell函数可以写return语句用来返回特定的值,假如未写return语句,默认返回0;函数的返回值范围只能是0~255.

有时候我们需要给定一个函数的返回值来确定函数的执行状态,就需要指定返回的状态码,状态码默认存储在$?变量中,未写明的话直接返回0.

假如需要返回一个字符串,我们可以使用echo <string>的形式来返回需要的字符串,$?变量中存储的仍是函数return的数字,而真正的内容则存储在$(function_name)中。

修改程序如下,测试返回值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/bash
function foo(){
echo "foo param 0=$0"
echo "foo param 1=$1"
echo "foo param 2=$2"
echo "foo param 3=$3"
}
foo hello world
echo foo return value = $?


function zoo(){
echo zoo
echo after
return 11
}
zoo
echo "zoo return int value = $?"
echo “zoo return string value=$(zoo)”

函数测试了上面的说明语句,foo函数未指定return值,zoo函数输出了两个字符串zooafter,并且返回值为11.执行脚本输出如下:

1
2
3
4
5
6
7
8
9
foo param 0=/bin/bash
foo param 1=hello
foo param 2=world
foo param 3=
foo return value = 0
zoo
after
zoo return int value = 11
“zoo return string value=zoo after”

可以看到如上所说,并且所有的echo语句都会存储在变量中。

4.局部变量

在shell变量中讲过如何用local关键字声明一个局部变量。这种声明方式一般用在函数中,保持变量不会被提升到调用函数的环境中,从而不会产生变量污染。

此处讲另一种方式,用()包裹的变量作用域同样只在括号范围内,不会产生变量污染。那么用括号包裹的命令集会不会是在子进程的shell中执行的呢?验证一下,编写程序如下:

1
2
3
4
5
6
7
8
9
function parent()
{
echo "this is function process id:$$"
(a=10;echo "this is child fucnton process id:$$")
echo this is a varibale $a
}
echo this is out of function process id: $$

(parent)

很简单的程序,输出结果:

1
2
3
4
this is out of function process id: 41649
this is function process id:41649
this is child fucnton process id:41649
this is a varibale

进程id一致,且在括号外a变量无值。

所以,括号内声明的变量作用域只在括号内。

函数导出

环境变量可以导出变量,同样函数可以导出,导出后在子进程shell中就可以使用。

1
2
3
4
function foo(){
command;
}
export -f foo

这样即可。