shell 脚本编程之函数
函数定义和调用
function FUNCNAME()
{
}
函数的定义很简单,可以看到和 c 语言的函数定义方式很相似。function 关键字可以省略,省略之后的函数定义跟 c 语言相比就是少了函数返回类型而已。函数调用就更简单了,直接写函数名即可。
#!/bin/bash
FILE=./learn_break.sh
function countLine()
{
local i=0
while read line
do
let ++i
done < $FILE
echo $FILE have $i lines
}
echo call function callLine
countLine
执行结果
call function callLine
./learn_break.sh have 15 lines
函数返回值
函数定义的时候不需要声明返回类型,是函数只能返回整数。可以使用 return 显式地让函数返回某个数,默认返回 0 表示函数正常执行完。函数返回值不一定要放在最后,可以放在前面提前结束函数调用(lua 语言要求返回值必须是函数的最后一条语句)。
#!/bin/bash
FILE=./learn_break.sh
checkFileExist()
{
if [ -e $FILE ]; then
return 0
else
return 1
fi
}
echo call function checkFileExist
checkFileExist
if [ $? -eq 0 ]; then
echo $FILE exist
else
echo $FILE not exist
fi
执行结果
call function checkFileExist
./learn_break.sh exist
函数参数
前面的例子函数都不能带参数,像检查文件是否存在的脚本,文件名直接写死了,这样如果要检查另一个文件又得修改脚本的内容。因此,函数参数就显得非常重要。shell 不同于 c 语言,不能显式定义形参和实参,而是跟脚本调用一样,使用位置参数。函数体内,使用 $1 到第一个参数的值,依此类推;函数调用时,直接在函数名后面带上参数即可,第一个参数将赋值给函数内的 $1,依此类推。
#!/bin/bash
function checkFileExist()
{
if [ -e $1 ]; then
return 0
else
return 1
fi
}
echo call function checkFileExist
checkFileExist $1
if (($?==0)); then
echo $1 exist
else
echo $1 no exist
fi
执行结果
[[email protected] ~]$ ./learn_function3.sh noexistfile
call function checkFileExist
noexistfile no exist
[[email protected] ~]$ ./learn_function3.sh learn_break.sh
call function checkFileExist
learn_break.sh exist
执行脚本时把文件名作为第一个参数传进去,此时脚本的 $1 保存的就是文件名;然后调用函数时把脚本的 $1 作为第一个参数传进去,此时函数内的 $1 也是文件名。参数的传递过程是外部传到脚本,再从脚本传给函数。注意脚本中的 $1 和函数内的 $1 是不一样的概念。看看下面的例子
#!/bin/bash
foo()
{
echo '$1 in function is '$1
}
foo 10
echo '$1 out of function is '$1
执行结果
[ljx@localhost ~]$ ./learn_function4.sh 100
$1 in function is 10
$1 out of function is 100
函数内的 $1 是函数调用时传进去的第一个参数,本例子中传了数字 10;而脚本内的 $1 是脚本执行时传进去的参数,本例子中传了数字 100。脚本本身维护了一个位置参数列表,每个函数也维护了一个位置参数列表,两者之间互不干扰。
重置位置参数
使用 set 关键字可以重置脚本或函数的位置参数,重置后外部调用传进来的位置参数将被覆盖。
#!/bin/bash
function foo()
{
echo function args list begin set: $1 $2 $3
set 1 2
echo function args list after set: $1 $2 $3
}
foo 10 20 30
echo script args list begin set: $1 $2 $3
set 128 256
echo script args list after set: $1 $2 $3
执行结果
[[email protected] ~]$ ./learn_function5.sh -1 -2 -3
function args list begin set: 10 20 30
function args list after set: 1 2
script args list begin set: -1 -2 -3
script args list after set: 128 256
set 重置的是整个位置参数列表,因此本例子中重置参数后,$3 就变成空了。这里也能再次看出脚本参数与函数参数相互独立。
移动位置参数
使用 shift 关键字可以左移位置参数,shift 后面带一个数字表示左移几位,默认不带的话表示左移一位。左移一位之后,原来 $1 的值就丢失了,$2 的值赋给 $1,$# 减一。
#!/bin/bash
offset=$1
shiftTest()
{
until ((0))
do
echo now '$1' is $1,total parameter is $#
if [[ $# -lt $offset ]]; then
break
fi
shift $offset
done
}
shift
shiftTest [email protected]
执行结果
[[email protected] ~]$ ./learn_function6.sh 1 10 20 30
now $1 is 10,total parameter is 3
now $1 is 20,total parameter is 2
now $1 is 30,total parameter is 1
在这个脚本中,先把脚本的第一个位置参数保存到 offset 变量中,表示每次向左移几位。然后把脚本剩下的位置参数传给函数,这样函数得到的位置参数就是脚本的位置参数除掉第一个。