2 shell函数参数

  • 2.1 位置参数
  • 2.2 选项参数
  • 2.2.1 getopts、getopt的区别
  • 2.2.2 getopts的使用
  • 2.2.3 getopt的使用


Shell 函数参数的传递和其它编程语言不同,没有所谓的形参和实参,在定义函数时也不用指明参数的名字和数目。换句话说,定义 Shell 函数时不能带参数,但是在调用函数时却可以传递参数。
Shell 中函数获取参数的方式和Shell 脚本获取脚本参数的方式一致. 需要注意的是$0 即使在函数中也代表脚本名称, 而非函数名称。

2.1 位置参数

函数参数是 Shell 位置参数 的一种,在函数内部可以使用$n来接收,例如,$1 表示第一个参数,$2 表示第二个参数,依次类推。

除了$n,还有另外三个比较重要的变量:

  • $#可以获取传递的参数的个数;
  • $@或者$*可以一次性获取所有的参数;

$n、$#、$@、$* 都属于特殊变量,不了解的请转到《Shell变量》。

在使用$@ 或者 $* 时建议用引号包裹, 否则当参数出现空格时, 会出现意想不到的效果
shift 表示从参数列表里弹出一个参数, 会影响$@, $#, $*的值

例1
使用 $n 来接收函数参数。

#!/bin/bash

#定义函数
function show(){
    echo "Tutorial: $1"
    echo "URL: $2"
    echo "Author: "$3
    echo "Total $# parameters"
}

#调用函数
show C# http://c.xxxx.net/csharp/ Tom

运行结果:

Tutorial: C#
URL: http://c.xxxx.net/csharp/
Author: Tom
Total 3 parameters

例2
函数位置参数测试

#!/bin/bash
test_param(){
  echo "脚本名称: $0"
  echo "参数个数: $#"
  echo "所有参数: $*"
  echo "所有参数数组: $@"
  echo "第1个参数: $1"
  echo "第10个参数: ${10}"

  echo '********* 参数遍历$@ **********'
  for arg in "$@"
  do
     echo $arg
  done

  echo '********* 参数遍历$* **********'
  for arg in "$*"
  do
     echo $arg
  done

  echo '********* 弹出式遍历 **********'
  while (( $# > 0 ))
  do
     echo "弹出参数:$#, 参数剩余:$# 个"
     shift
  done
}

# 调用函数 
test_param 1 2 3 4 5 6 7 8 9 10 11 12

运行结果

脚本名称: ./test.sh
参数个数: 12
所有参数: 1 2 3 4 5 6 7 8 9 10 11 12
所有参数数组: 1 2 3 4 5 6 7 8 9 10 11 12
第1个参数: 1
第10个参数: 10
********* 参数遍历$@ **********
1
2
3
4
5
6
7
8
9
10
11
12
********* 参数遍历$* **********
1 2 3 4 5 6 7 8 9 10 11 12
********* 弹出式遍历 **********
弹出参数:12, 参数剩余:12 个
弹出参数:11, 参数剩余:11 个
弹出参数:10, 参数剩余:10 个
弹出参数:9, 参数剩余:9 个
弹出参数:8, 参数剩余:8 个
弹出参数:7, 参数剩余:7 个
弹出参数:6, 参数剩余:6 个
弹出参数:5, 参数剩余:5 个
弹出参数:4, 参数剩余:4 个
弹出参数:3, 参数剩余:3 个
弹出参数:2, 参数剩余:2 个
弹出参数:1, 参数剩余:1 个

shift命令

shift命令用于对参数的移动(左移),通常用于在不知道传入参数个数的情况下依次遍历每个参数然后进行相应处理。

例3

[root@server1 mnt]# cat test.sh 
#!/bin/bash
while [ $# != 0 ];do
echo "第一个参数为:$1,参数个数为:$#"
shift
done

运行结果

[root@server1 mnt]# sh test.sh a b c d e f
第一个参数为:a,参数个数为:6
第一个参数为:b,参数个数为:5
第一个参数为:c,参数个数为:4
第一个参数为:d,参数个数为:3
第一个参数为:e,参数个数为:2
第一个参数为:f,参数个数为:1

#从上可知 shift(shift 1) 命令每执行一次,变量的个数($#)减一
#(之前的$1变量被销毁,之后的$2就变成了$1),而变量值提前一位

2.2 选项参数

在执行shell脚本时,可以像运行应用程序一样传入相应的参数,在脚本内部根据传入的参数内容执行和它对应的操作。shell脚本中可以通过"$1……$N"形式的符号来引用传入的参数,1~N和传入参数位置相对应的,比如$1表示执行脚本时传入的第一个参数,$2表示传入的第二个参数,以此类推此后传入参数的引用。

对于一些只需要很简单的命令行参数的脚本,通过使用$N形式轻松的完成解析,但对于比较复杂的命令行形式的参数,就需要脚本的编写者在脚本中加入复杂的代码对命令行进行解析。

为了减少重复性编程和简化命令行参数处理的过程,shell中为脚本编写者提供了一些命令行处理方法,使用这些方法可以轻松的处理各种形式的命令行参数。这里讲的getopt、getopts就是其中的一些,下面我们来详细介绍如何使用getopt、getopts处理命令行参数。

2.2.1 getopts、getopt的区别

在介绍如何使用getopts、getopt处理命令行参数之前,先来简单的说下getopt、getopts两者的各种特点和区别

首先来说getopts,getopts是shell中内建的命令,它的使用语法相对getopt简单,但它不支持长命令参数(–option)。它不会重排列所有参数的顺序,选项参数的格式必须是-d val,而不能是中间没有空格的-dval,遇到非-开头的参数,或者选项参数结束标记–就中止了,如果中间遇到非选项的命令行参数,后面的选项参数就都取不到了,出现的目的仅仅是为了代替getopt较快捷方便的执行参数的分析。

相反的是,getopts的缺点正好是getopt所具有的优点。相对于getopts而言,getopt是一个独立的外部工具(Linux的一个命令),它的使用语法比较复杂,支持长命令参数,会重排参数的顺序。在shell中处理命令行参数时,需要配合其他Linux命令一起使用才行。

总的来说getopts和getopt相比,getopts使用起来比较简单,但只支持短参数,getopt使用起来虽比较复杂,但处理的参数类型比较广泛

2.2.2 getopts的使用

(1 )命令格式

getopts optstring name [arg]
  • optstring:以冒号为分隔的选项。表示要识别的命令行选项形式,如果一个字母后面有一个":",表示该命令行选项后面要跟一个参数。如optsting写成"co:f:",表示支持-c、-o、-f选项识别,-o和-f选项后面需要跟一个参数
  • name:每次调用它前,getopts都会将下一个选项放置在shell变量$name中,如果传入命令行中不存在name选项,则将其重新初始化
  • arg:表示要解析参数,在shell脚本中使用时,默认解析的是执行shell脚本传入的参数,所以这个部分可省略不写

特殊的getopts变量

当匹配到一个需要参数的选项时,getopts将选项后面跟的参数存放到shell中的OPTARG变量里,OPTIND表示下一个要被处理的命令行参数的索引。

OPTIND:初始化为1, 每次getopts处理完一个命令行选项后,OPTIOND就增加为getopts要处理的下一个选项的序号

OPTARG:包含了对应variable的选项的参数的值

这里还要注意一下optstring 开始部分有与没有冒号的区别:

1)前面没有冒号:

会按照系统的定义报错

a. 指定了非法选项,即不存在的选项,会报错:scriptname: illegal option — p

b. 选项需要参数但没有指定,会报错:scriptname: : option requires an argument –

c 不论是指定了错误的选项或者指定了带选项的参数没有指定参数,variable都设置为”?”,对应的OPTARG为出错的选项

2)选项前面有冒号,可以屏蔽这些错误信息,使用自己的反馈信息

a. 当指定的参数不存在时,variable设置为”:”,对应的$OPTARG为”对应的选项”

b. 指定的选项是带参数的而没有提供参数,variable设置为”?”,对应的$OPTARG为”这时候的选项”

可以根据这两个选项指定不同的反馈信息,也就是我们可以控制这些信息了

(2)命令使用

在这里插入代码片

2.2.3 getopt的使用

1)命令格式

getopt是Linux中的一个命令,通常位于/usr/bin目录中,它可以接受一系列任意形式的命令行选项和参数,并自动将它们转换成适当的格式。getopt的命令使用有一下的三种格式:

getopt optstring parameters
   getopt [options] [--] optstring parameters
   getopt [options] -o|--options optstring [options] [--] parameters

getopt的参数分为两部分:用于修改getopt解析模式的选项(即语法中的options和-o|–options optstring)和待解析的参数(即语法中的parameters部分)。第二部分将从第一个非选项参数开始,或者从"–“之后的第一项内容开始。如果在第一部分中没有给定”-o|–options",则第二部分的第一个参数将用作短选项字符串。

如在Linux的Terminal中输入:get c:b -c file -b home

返回匹配结果如下:

-c file -b -- home

输出结果分为两部分,"–“之前的是模式的匹配的结果,”–"之后的是非选项类型的参数

所谓的非选项类型的参数,即是在parameters中,一个不是以"-"开头,也不是它前面的选项所需的参数,那么它就是一个非选项类型的参数(比如上述输入paramters中的home)。