参数的处理方法
和命令的选项和参数一样,执行脚本的时候可以指定传进来的选项和参数,什么是选项什么是参数就不多说了。向Shell中传递的参数叫命令行参数,传进来的参数将会被赋值给一些特殊变量,这些变量称为位置参数,这些变量利用数字表示,其中$0表示命令名称,$1表示第一个参数,$2表示第二个参数,以此类推。如果参数很多,比如15个,那么最后一个参数用${15}表示,注意要用大括号,传入的参数之间用空格分隔。例如:
1 |
|
执行上述脚本就会打印脚本名称和第一个参数了。如下所示:

可以看到$0实际上是包含了脚本的完整路径的,对此,可以利用basename命令获取脚本名称。如下处理,就可以获取脚本名了(带后缀):
1 | name=$(basename "$0") # 添加双引号以防路径中有空格 |
此外,传如的参数处理上述的特殊变量外,还有几个特殊变量与参数相关,分别是(都不包括$0):
$#:表示参数的个数;$*:表示传进来的所有参数,是一个整体;$@:表示传进来的所有参数,与第二个区别是,这里每个参数单独是一个个体。
1 | for item in "$*" |
参数处理
参数处理其实可以有很多方式,比如直接对$@遍历,或者利用$#计数循环,每次都拿出一个参数进行判断处理。但是,这种处理方式很不方便,稍微复杂一点的参数处理起来就很麻烦了。通常可以利用shift、getopt和getopts对参数进行处理。
shift
shift是移位命令,可以对传入参数进行左移,后面可以带一个整数表示左移多少个,默认是1。左移一位就是,原来的$3变成了$2,$2变成了$1,$1将被丢弃,其他的情况类似,$0始终不变。例如下面脚本将会不断输出传入的参数,直到全部输出位置:
1 | while [ -n "$1" ] |
需要注意的是,执行shift之后,丢弃的参数将不可恢复。通常会结合case命令一起,达到处理不同参数的效果:
1 | while [ -n "$1" ] |
上述脚本将支持两个选项,-a和-b,比如其名称是test.sh,可以这样执行: ./test.sh -a -b,从而达到达到了处理参数选项的效果。
getopt
getopt命令用户对输入参数的调整,使得处理起来更方便,其基本使用方法为:
1 | getopt option optstring parameter |
执行getopt命令后将输出调整后的参数,例如:
1 | getopt ab:c -a test1 -b test2 -c test3 test4 |
可以看见输出后得到的参数更加规范,下面对optstring进行简要说明。optstring定义了选项有哪些以及那些选项带有参数。具体格式是,各个选项字母组成的字符串,某个选项需要带参数的则在对应字母后面加一个冒号(一个表示必选参数,两个表示可选),最终得到的字母和冒号组成的字符串就是optstring了。
此外,getopt还支持长选项,类似于单字母选项,如下例子(用-l指定长选项optstring):
1 | getopt -o a -l along,blong:,clong:: -- --along --blong=1 --clong test -a |
optstring类似于单字母选项,仅仅是选项之间用逗号分隔,其他规则一样。有了这些理解,详细的使用方法可以查看命令手册,在终端执行man getopt即可查看。
optget命令得到的输出按optstring,选项和参数以此排列,如上述例子。需要注意的是,该命令不能处理参数中的空格,即便加了双引号也会当成两个参数。最后需要说明的是,命令行中的破折号(两个连续的减号)参数,表示的是其后面的全部是参数,没有选项,即便写成-a这种形式,也不会把它当选项处理,只看做是参数。
有了getopt命令的参数调整,需要用set命令将这些参数覆盖掉特殊变量中的参数,具体为:
1 | set -- parameter |
表示用parameter替换掉原来的命令行参数。因此,结合getopt,可以这样替换原来的参数:
1 | set -- $(getopt option optstring "$@") |
这样一来,诸如$1这些特殊变量就按照getopt命令输出内容决定了。然后结合shift和case,参数处理起来就简便了不少。
getopts
getopts是另外一个参数处理命令,其使用方法为:
1 | getopts optstring variable [arg] |
每次得到待处理的选项赋值给上述的variable。其中optstring格式和getopt类似。如果需要禁用错误输出,只需optstring以冒号开头即可。
需要注意的是:
- 得到的选项将不包含开头的
-,比如有-a选项,则变量variable中的值是a。如果某个选项不在optstring定义的选项中,则variable中存的值统一都是?(问号); getopts不支持长选项,支持多个选项放一起,如-ac和-a -c一样效果;getopts参数和选项之间可以没有空格,如-aarg和-a arg一样;getopts能够识别出双引号参数中的空格,即不会当成多个参数处理。
当getopts待处理的下一个参数不是选项时,getopts就以非零退出状态退出了,所幸,getopts还提供了另外一个环境变量:OPTIND,保存的是一个整数,表示了待处理的下一个参数所在的位置,利用该环境变量,就可以很方便获取上下没出来那些没有对应选项的参数。下面是一个例子:
1 |
|
上面的例子因为遇到第一个非选项的参数的时候就退出循环了,而利用getopt的特性:把所有选项都调整在前面,因此可以结合两个命令一起用,效果就比较好了,例如:
1 |
|
这样的话在循环中就可以处理完所有参数,而剩下的无选项参数全部放在了最后。
注意: 这里因为先用到了getopt调整参数,因此参数需要满足其使用特征,例如不支持选项和参数之间没有空格等等这种仅仅getopts支持的特征。