shell-函数之参数使用详解
参数的调用方法
在其他语言中,函数参数分为形参和实参,其中,形参是函数定义时就指定的参数;而实参是函数被调用时才指定的参数(通常放在括号里,参数之间用逗号隔开)
shell的函数参数比较特殊,实际上shell将脚本的参数和函数的参数统一处理,怎么调用脚本参数就怎么调用函数参数。
function_name arg arg1 arg2 ...
function_name是函数名,arg表示函数参数,通过空格隔开。
通过位置变量接受函数参数
和shell脚本相同,shell函数通过系统变量获取参数值。
从命令行传递给shell函数的参数叫做位置参数,shell会根据参数的位置来接受对应的值。
在shell内部,用户可以通过一系列的系统变量来获取参数,这些变量的名称都是固定的,非常简单,只用一个字符表示,例如$0表示脚本名称;$1表示传递的第一个参数......
常用于参数传递的系统变量
变量 | 说明 |
---|---|
$n | n是一个参数,从1开始表示参数的位置,例如:$1表示第一个参数,$2表示第二个参数 |
$# | 命令行参数的个数 |
$0 | 当前shell脚本的名称 |
$? | 前一个命令或者是函数的返回状态码,0代表执行成功,非0即失败 |
$* | 以”参数1参数2....“的形式将所有函数通过一个字符串返回 |
$@ | 以”参数1“”参数2“....的形式返回每个参数 |
$_ | 保存之前执行的命令的最后的一个参数 |
举个简单的例子:
#!/bin/bash
func ()
{
echo "这是第 $2 个参数"
echo "这是第 $4 个参数"
echo "这是第 $1 个参数"
}
func 1 2 3 4
输出结果为:
shift移动位置参数
shift命令可以使位置参数向左移。比如shift 3表示位置参数$4 向左移动三变成 $1,原来的$5现在变成$2,而原来的$1、$2、$3丢弃,** 因为$0是脚本名嘛!**。不带参数的shift命令相当于shift 1。
我们知道,对于位置变量或命令行参数,其个数必须是确定的,或者当 Shell 程序不知道其个数时,可以把所有参数一起赋值给变量$*。若要求 Shell 在不清楚位置变量个数的情况下,依次遍历每个参数然后进行相应处理。
例如:
#!/bin/bash
func ()
{
while [ $# -ne 0 ]
do
echo "第一个参数为:$1 ,一共有$# 个参数"
shift
done
}
func 1 2 3 4 5 6
用祖传画图来尝试画个示意图
-
Shift 命令还有另外一个重要用途, Bsh 定义了9个位置变量,从 $1 到 $9,这并不意味着用户在命令行只能使用9个参数,借助 shift 命令可以访问多于9个的参数。
-
Shift 命令一次移动参数的个数由其所带的参数指定。例如当 shell 程序处理完前九个命令行参数后,可以使用 shift 9 命令把 $10 移到 $1。
-
shift会影响系统变量$#的值 _
通过getopts接收函数参数
所有学习Unix或Linux的人,都会记得这样一句话:命令+参数+选项;例如ls -l,这个“ -l ”也是个参数,只不过这个参数有一个前导的连字符。
通过上面的步骤已经可以通过$1,$2...获取全部参数,还可以通过$#来获取参数的个数;但是我们的脚本程序不会这么简单,一个参数往往有很多的值,根据参数的值执行不同的操作,这时就会用到一种技术——参数拓展
getopts是bash内嵌的一个命令。通过该命令可以获得函数的选项和参数值或者是脚本的命令行选项和参数值。语法为:
getopts optstring [args]
optstring包含一个被getopts识别的选项名称列表。如果某个选项后面跟着一个冒号,表示可以为该选项提供参数值。同时参数值将被保存到一个名称为$OPTARG的系统变量中。getopts遍历每个选项,将选项名保存到args变量中。
#!/bin/bash
func ()
{
while getopts "a:b:c:" arg
do
case "$arg" in
a)
echo "-a表示all全部。。。参数值为; $OPTARG"
;;
b)
echo "-b表示返回。。。参数值为: $OPTARG"
;;
c)
echo "-c还没想好。。。参数值为:$OPTARG"
;;
?)
echo "没有找到这条命令。。。。"
exit 1
;;
esac
done
}
func -a "你好" -b "hello" -c "ARE YOU OK?"
输出结果为:
间接参数传递
所谓间接参数传递,就是指通过间接变量引用来实现函数参数的传递。
一个变量的值是另一个变量的变量名,则该变量就可以说是间接变量
例如:
var=work
work=job
此时引用变量work就可以用:
${!var}
举个简单的示例:
#!/bin/bash
func ()
{
echo "$1"
}
var=work #定义变量var的变量值为work
work=job #定义变量work的变量值为job
func $var #将$var作为函数参数
func $work #直接引用$work作为函数参数
func ${!var} #使用间接参数传递的方式调用$work的值
work=test #重新定义变量work的值为test
func $var
func ${!var} #再次传递参数试试
输出结果为:
全局变量传递
原理很简单,就是通过全局变量的替换来实现参数传递(不建议这样写,因为过段时间可能就只有上帝才能看懂这段代码)
定义一个函数判读文件是否存在
#!/bin/bash
file="/bin"
func ()
{
if [ -a "$file" ];then
echo "文件存在"
else
echo "文件不存在"
fi
}
func
file="/asdawdaasf"
func
输出结果为:
数组传递参数
将整个数组作为参数传递给函数(将数组中的元素展开,看成是由空格隔开的参数传递给函数)
例如:
#!/bin/bash
array=(a b c d e "f g" )
func ()
{
echo "参数个数为: $# "
while [ $# -gt 0 ]
do
echo $1
shift
done
}
func "${array[@]}"
输出结果为