Linux shell脚本编程之函数

在编写功能比较复杂的shell脚本时,完成具体任务的代码有时会被重复使用,bash shell脚本提供函数特性实现代码复用,函数是被赋予名称的脚本代码块。

一、创建函数
在bash shell脚本中创建函数的格式如下:

function name()
{
    commands
}	
一个简单的例子如下:
$ cat test.sh
#!/bin/bash
function func_test(){
    echo "hello world"
}
func_test;
$ ./test.sh
hello world
注意:函数要在使用前定义,使用没有定义的函数会报错。
二、函数的返回值
bash shell将函数看作是一个小型的脚本,函数的退出码(即返回值)有三种形式:
(1)默认退出状态
与一般脚本相同,在函数执行完后,函数的退出码存放于变量$?中。

$ cat test.sh
#!/bin/bash
function func_test(){
    echo "hello world"
}
func_test;
echo "func_test的返回值为:$?"
$ ./test.sh
hello world
func_test的返回值为:0
可以看出函数的默认返回值为0,但是最好不要使用函数的默认返回值,看下面这个例子

$ cat test.sh
#!/bin/bash
function func_test(){
    ls -l /xxx/xxxx  #/xxx/xxxx是一个不存在的文件夹
    echo "program end"
}
func_test;
echo "func_test的返回值为:$?"
$ ./test.sh
ls: 无法访问'/xxx/xxxx': 没有那个文件或目录
program end
func_test的返回值为:0
可以看出 ls -l 命令执行失败,但是函数返回值却是0,因为最后一条命令echo能够正确执行。函数的返回值是最后一条命令的返回值。我们执行func_test后,根据返回码无法判断ls -l命令是否执行成功,这明显不是一个好的做法。
(2)在函数中使用return命令返回指定状态码
$ cat test.sh
#!/bin/bash
function func_test(){
    if ! ls -l /xxx/xxxx  #/xxx/xxxx是一个不存在的文件夹
    then 
         return 1
    fi
    echo "program end"
}
func_test;
echo "func_test的返回值为:$?"
$ ./test.sh
ls: 无法访问'/xxx/xxxx': 没有那个文件或目录
func_test的返回值为:1
ls -l 命令执行失败,函数退出,返回码为1。有两点一定要注意:
1、函数的返回码跟脚本返回码一样,取值范围为0~255
2、函数返回值在函数执行完后最好立即取出。(如果在函数后又执行了其它命令,函数的返回码会被命令的返回码覆盖)

(3)函数输出
  使用函数输出将函数输出存放到shell变量中,这样我们可以从函数获取任意类型的输出。
$ cat test.sh
#!/bin/bash
function func_add(){
    read -p "请输入两个整数:" a b 
    echo $[ $a+$b ]
}
result=`func_add`;
echo "两个数的和为:$result"
$ ./test.sh
请输入两个整数:100 300
两个数的和为:400
三、向函数中传递参数
  与向脚本传递参数相同,参见 Linux shel编程之命令行参数处理:
 这里只给出一个简单例子:
$ cat test.sh
#!/bin/bash
function func_add(){
    echo $[ $1+$2 ]
}
read -p "请输入两个整数:"  a b
result=`func_add $a $b`;
echo "两个数的和为:$result"
$ ./test.sh
请输入两个整数:100 200
两个数的和为:300

四、在函数中使用变量

变量作用域是shell脚本程序员遇到的常见的问题,使用域是变量的可见区域。函数内定义的变量与普通变量有着不同的作用域。函数内可以使用两种类型的变量:全局变量和局部变量
1.全局变量
全局变量是在shell脚本内处处可以使用的变量,如果脚本的主代码定义了全局变量,那在函数内部可以使用这个变量的值,同样,如果在函数内部定义了全局变量,那在脚本的主代码中也可以使用这个变量的值。默认情况下,脚本中定义的变量都是全局变量,使用全局变量时应该非常小心:

$ cat test.sh
#!/bin/bash
function test_global
{
 value=$[$value*2]
 temp=$value
}

value=12
test_global
echo "value=${value}"
echo "temp=${temp}"
$ ./test.sh
value=24
temp=24
2.局部变量
只能在函数内部使用的变量称为局部变量,声明局部变量时要在变量名前加上"local"关键字
$ cat test.sh
#!/bin/bash
function test_global
{
  local value=24
  echo "local value=${value}"
}

value=12
test_global
echo "global value=${value}"
$ ./test.sh
local value=24
global value=12
五、数组变量与函数

1.数组变量
数组是能保存多个值的变量,数组中的值可以单个引用,也可以作为一个整体引用。

$ cat test.sh
#!/bin/bash
array=(1 2 3 4 5)
echo ${array}
echo ${array[2]}
echo ${array[*]}
array[2]=333
echo ${array[*]}
$ ./test.sh 
1
3
1 2 3 4 5
1 2 333 4 5
从上面例子可以看出:如果直接使用${array}只能得到第一个元素。使用${array[n]}可以根据下标索引获取数组中元素。如果想得到整个数组的值就要使用echo ${array[*]},还可以直接修改数组元素的值。

2.向函数传递数组

要想把数组变量传递给函数,如果把数组变量作为单个参数传递,会得到意想不到的结果。

$ cat test.sh
#!/bin/bash
function test_array
{
   echo "The parameters are:$@"
}

array=(1 2 3 4 5)
test_array ${array}
$ ./test.sh
The parameters are:1
显然直接将数组变量作为函数参数使用,那么只能得到数组变量的第一个元素。将数组变量拆分为单个元素可以解决这个问题。
$ cat test.sh
#!/bin/bash
function test_array
{
   echo "The parameters are:$@"
   new_array=(echo "$@")
   echo "new_array: ${new_array[*]}"
   sum=0
   for val in ${new_array[*]}
   do
       sum=$[${sum}+${val}]
   done
   echo "the total of array is :${sum}"
}

array=(1 2 3 4 5)
test_array ${array[*]}
$ ./test.sh
The parameters are:1 2 3 4 5
new_array: echo 1 2 3 4 5
the total of array is :15
3.从函数返回数组
也可以从函数向shell脚本回传数组变量,利用函数输出以恰当的顺序输出各数组的值,然后脚本必须将这些数据重组为新数组变量。
$ cat test.sh
#!/bin/bash
function test_array
{
  ret_array=(1 2 3 4 5)
  echo "${ret_array[*]}"
}

array="(`test_array`)"
echo "the functon return:${array[*]}"
$ ./test.sh
the functon return:(1 2 3 4 5)
六、函数库 如果我们想在一个脚本a调用另一个脚本b定义的函数,即将脚本文件b当作一个函数库使用,利用source命令可以在脚本a内部运行脚本b(不创建新的shell执行脚本b),这样在脚本a中就可以使用脚本b种定义的函数。所以只需要在脚本a中加入 

source  /..../b.sh或.  /...../b.sh即可,/....../b.sh表示脚本b的路径

.与source在此处含义相同。

$ cat add.sh
#!/bin/bash
function add()
{
  echo $[$1+$2]
}
$ cat test.sh
#!/bin/bash
. ./add.sh
result=`add 1 2`
echo "1,2相加的和为:$result"
$ ./test.sh
1,2相加的和为:3

你可能感兴趣的:(Linux编程)