Shell脚本:命令选项参数处理
Shell脚本的参数处理主要分三种情况,下面我们一一演示说明。
1、不带选项的参数处理
首先,我们通过一个不带选项的参数处理脚本,让大家了解一下Shell脚本的常用内置参数。
#!/bin/bash
echo $0 # 脚本名, 带执行时的路径,类似于C语言中的argv[0]
echo $1 # 参数1
echo $2 # 参数2
echo $3 # 参数3, 以此类推
echo $# # 参数个数, 不包含脚本本身
echo $@ # 参数列表
echo $* # $*与$@相同, 但"$*"与"$@"不同, "$*"将所有参数解释为一个字符串, 而"$@"是一个参数数组.
把上面这段脚本保存到arg.sh中,然后执行脚本将显示这些Shell内置参数值:
[root@HLZ arg_proc]# dos2unix *.sh # 语系转换为类unix方格
dos2unix:converting file arg.sh to UNIX format ...
[root@HLZ arg_proc]# ./arg.sh z yy zzz jkl
./arg.sh
z
yy
zzz
4
z yy zzz jkl
z yy zzz jkl
显然地,不带选项的参数处理可以满足固定参数的脚本编写需求,但是对于可变参数或者复杂参数情况,就需要脚本中带选项的参数处理方式了!
2、短选项参数处理
Shell脚本中短选项参数的处理,完全可以使用while…shift…语句实现。当然,此处为了简化步骤,我们借助bash的内置命令getopts实现。
#!/bin/bash
# 选项后面不带:表示无参数, 带:表示有参数
while getopts "ab:" arg
do
case $arg in
a)
echo "Optiona";;
b)
echo "Option b: ${OPTARG}";;
esac
done
shift $((OPTIND-1)) #执行该语句,以便本脚本后面固定参数序号从$1开始.
echo "Process arg: $1"
echo "Process arg: $2"
将上面这段脚本保存到getopts.sh中,然后执行:
[root@HLZ arg_proc]# dos2unix *.sh
dos2unix:converting file getopts.sh to UNIX format ...
[root@HLZ arg_proc]# ./getopts.sh -b xyz -a arg1 arg2 #例2.1
Optionb: xyz
Option a
Process arg: arg1
Process arg: arg2
[root@HLZ arg_proc]# ./getopts.sh -b xyz -a -c arg1 arg2 #例2.2
Optionb: xyz
Optiona
./getopts.sh: illegal option -- c #对于不支持的选项,由getopts报错.
Processarg: arg1
Processarg: arg2
[root@HLZ arg_proc]#./getopts.sh -b -a xyz arg1 arg2 #例2.3
Option b: -a
Process arg: xyz
Process arg: arg1
如例2.3所示,对于不支持的选项,getopts会报错,但不退出而是继续执行。
执行脚本时,对选项参数是没有顺序要求的,但是如例2.3所示,-b选项实现时是要求带参数的,但是执行时没有带参数,导致getopts把后面的-a解析为参数了,而且解析不到-a选项了!!这是由于执行时参数输入错误导致的,当然为了增强脚本的鲁棒性,可以对选项-b的参数进一步做个判断:若参数是本脚本的另一个选项,则报错退出。
带短选项参数的处理方式基本能够满足shell脚本的写作需求。
当然为了脚本选项参数的意义更加简明易懂,我们接下来继续介绍长选项参数的处理方法。
3、长选项参数处理
Shell脚本长短选项参数的处理,使用getopt和while…shift…语句实现。
#!/bin/bash
# -o或--options, 后面接短选项; -l或--long, 后面接长选项;
# 多个长选项之间用,分隔, 类似于短选项, 选项后面不带:表示无参数, 带1个:表示有参数, 而带2个::表示参数可有可无.
ARGS=`getopt -o xy:z:: -l xlong,ylong:,zlong:: -n 'getopt.sh' -- "$@"`
if [ $? != 0 ]; then
exit 1
fi
eval set -- "${ARGS}" # 将规范化的参数分配至位置参数($1,$2,...)
while true
do
case $1 in
-x|--xlong)
echo "Option x"; shift;;
-y|--ylong)
echo "Option y: $2"; shift 2;;
-z|--zlong)
case $2 in
"")
echo "Option z: no argument"; shift;;
*)
echo "Option z: $2"; shift 2;;
esac;;
--)
shift; break;;
esac
done
# 处理剩余参数
for arg in $@
do
echo "Process $arg"
done
将上面这段脚本保存到getopt.sh中,然后执行:
[root@HLZ arg_proc]# dos2unix *.sh
dos2unix:converting file getopt.sh to UNIX format ...
[root@HLZ arg_proc]# ./getopt.sh -x -y 123 -z456 arg1 arg2 #例3.1
Option x
Option y: 123
Option z: 456
Process arg1
Process arg2
[root@HLZ arg_proc]# ./getopt.sh --ylong 123 -x --zlong=456 arg1 arg2 #例3.2
Option y: 123
Option x
Option z: 456
Process arg1
Process arg2
[root@HLZ arg_proc]# ./getopt.sh --ylong 123 -v --zlong=456 arg1 arg2 #例3.3
getopt.sh:invalid option -- 'v'
[root@HLZ arg_proc]# ./getopt.sh --ylong -x arg1 --zlong=456 arg2 #例3.4
Option y: -x
Option z: 456
Process arg1
Process arg2
如上面执行结果所示:
例3.1中,选项与参数之间一般用空格隔开,但是-z与参数456之间没有空格,而选项参数能正常解析,是因为语句eval set -- "${ARGS}"起了作用。
例3.2中,可以看出长选项参数于选项之间即可用空格间隔,亦可直接用=号,即--zlong=456。
例3.3中,对于不支持的选项,如上面的-v,getopt将报错并直接退出,这是与getopts不同的地方。
例3.4中,首先,类似于短选项参数存在的问题,--ylong选项实现时是要求带参数的,但是执行时没有带参数,导致把后面的-x解析为参数,而解析不到-x选项了。同样的解决方法,对选项参数做个判断:若参数是本脚本的另一个选项,则报错退出。其次,由执行结果可见,getopt会把非选项参数按照原有参数顺序,归类并有序放在选项参数之后,如arg1 arg2。
与getopts不同的是,getopt是一个独立可执行程序,更详细说明可通过man getopt查看。