Shell中的函数、函数定义、作用域问题介绍
说起函数调用,相信大家也不会陌生,然而对于初学shell的我来说,shell中函数调用方式却有点让我不太习惯,自己也走了不少的弯路,因为传递参数时出了一个很“自然”的错误,也让我吃了不少的苦头,所以总结一下shell中函数的调用方法。
一、shell中函数的定义
为了方便程序和管理和模块化并减少代码的重复,函数的确是一个好东西。而shell中函数的定义有两种方法,如下:
function fname()
{
statements;
}
或
fname()
{
statements;
}
注意,()内是没有参数的,它并不像c语言那样,在()里可以有参数。
那大家可能就郁闷了,函数调用或多或少总是会需要一些参数,那么这些参数要怎么传递进来呢?其实参数传递方式为:fname;(不需要传递参数)或fname agr1 arg2(需要传递两个参数);
二、自定义函数的例子
不知道大家的情况如何,反正一开始我就觉得很别扭,因为在c语言中,例如我定义一个函数int cmp(int a, int b),那么我就会在函数中使用到函数头中声明的变量a和b,而在shell中却没有定义参数,那我的函数又需要用到这两个参数,怎么办好呢?下面就用一个例子来说明好了。
#! /bin/bash
# filename:loopprint.sh
function loopprint()
{
count=0;
while [ $count -lt $1 ];
do
echo $count;
let ++count;
sleep 1;
done
return 0;
}
read -p "please input the times of print you want: " n;
loopprint $n;
先来说说这个程序的功能吧,就是输入一个数字n,然后从0开始每隔1秒输入一个数字,直到输出n-1为止。首先,程序会要求你输入一个数学,然后调用函数来进行输出的功能。
注意注释1的那一句,里面有一个变量$1,大家应该还记得调用函数时参数的传递方式,即fname agr1 arg2,这里的$1就是表示第一个参数,依此类推,$2就是第二个参数,$3就是第3个参数,$n就是表示第n个参数。
所以$1就是变量n的值。这样说大家懂了吧!
补充一下,就是:
$0:是脚本本身的名字;
$#:是传给脚本的参数个数;
$@:是传给脚本的所有参数的列表,即被扩展为"$1" "$2" "$3"等;
$*:是以一个单字符串显示所有向脚本传递的参数,与位置变量不同,参数可超过9个,即被扩展成"$1c$2c$3",其中c是ifs的第一个字符;
$$:是脚本运行的当前进程id号;
$?:是显示最后命令的退出状态,0表示没有错误,其他表示有错误;
特别注意,传递参数时,(这个例子中)一定要写成loopprint $n;而不能写成loopprint n。为什么?例如你输入的是20,则n的值($n)为20,前者表示的是把n的值,即20传递给函数loopprint,而后者则表示把字符n传递给函数loopprint。这点与在静态语言中的函数参数传递是很不同的,因为在shell中变量的使用并不需要先定义,所以要使用变量,让shell知道它是一个变量,并要传递它的值时,就是用$n,而不能直接用n,否则只把n当作一个字符来处理,而不是一个变量。
三、作用域问题
函数的作用域与c/c++语言中的作用约束是一样的,函数的定义一定要出现在函数的调用语句之前,但是有一点跟c/c++中不一样的就是变量的作用域问题,经过本人的试验,在注释1的语句改为while [ $count -lt $n ];也是可行的,即函数可以使用本文件中出现的任何变量,但是本人还是建议使用上面例子中的方法,即while [ $count -lt $1 ],并且不要随意使用函数中的变量之外的变量,因为你并不一定知道你调用函数时函数外有什么变量存在也不知道它的值是什么,也不能保证别人在使用你的函数时会传递你在函数中使用到的变量名,如这里的n,别人在使用时可能传递的就是他自己定义的变量,如count等。