getopts
格式
1 #!/bin/bash
2 echo "begin index is $OPTIND"
3 echo "begin ARG is $OPTARG"
4
5 while getopts ":ab:c:" OPT
6 do
7 case $OPT in
8 a)
9 echo "$OPTIND=$OPTIND, a is $OPTARG, $1=$1, $OPTIND=$OPTIND";;
10 b)
11 echo "$OPTIND=$OPTIND, b is $OPTARG, $2=$2, $OPTIND=$OPTIND";;
12 c)
13 echo "$OPTIND=$OPTIND, c is $OPTARG, $3=$3, $OPTIND=$OPTIND";;
14 :)
15 echo "$OPTIND=$OPTIND, : is $OPTARG, $#=$@, $OPTIND=$OPTIND";;
14 ?)
15 echo "$OPTIND=$OPTIND" # OPTIND 已经指向下一个参数
16 shift $(($OPTIND-2)) # 仅针对下面测试的参数列表,这里需要 -2 才可以让当前参数 -d位于 $1(因为 -d 是非法选项,处理完之后,OPTIND只+1=6,需要把前面4个参数去掉)
17 echo "剩余参数列表:$@"
18 echo -e "Illegal option -- '$1'
Usage: `basename $0` [-a] [-b value] [-c value] args"
19 exit 2 ;;
20 esac
21 done
22 echo "end index is $OPTIND"
lfp@legion:~$ ./bin/getopts.sh -b bb -c cc -d 22 -a
begin index is 1 # 初始值为1
begin ARG is # 没有初始值
$OPTIND=3, b is bb, $2=bb, $OPTIND=3
$OPTIND=5, c is cc, $3=-c, $OPTIND=5
$OPTIND=6
剩余参数列表:-d 22 -a
Illegal option -- '-d'
Usage: getopts.sh [-a] [-b value] [-c value] args
区别 选项列表 参数列表
选项列表
命令可以接收的选项
参数列表
命令行中,除命令之外的字符组成参数列表。
./bin/getopts.sh -b bb -c cc -d 22 -a 参数列表为 -b bb -c cc -d 22 -a,对应的位置从1开始计算 选项的位置 -b(1),-c(3) 。因为-b带参数,所以OPTIND需要加2才能指向下一个选项, 由此可知,不带参数的选项,OPTIND只需要加1即可
getopts 从命令行前面开始处理。参数列表中包括选项和参数,选项通过
-
来区分,其他被视作选项的参数标准格式 while getopts "选项列表" OPT
选项列表字符串
- 前面加冒号
:
则表示当遇到选项列表之外的选项时,不会有警告信息(静默模式)- 一个字母代表一个选项
- 选项后面跟冒号
b:
表示该选项b,需要指定参数- 选项后面没有冒号
ab:
表示该选项a,不需要指定参数,也称作开关选项OPT
代表输入的参数
如果出现了选项列表之外的选项,OPT 会被设置为
?
如果缺少参数,分两种情况
如果选项列表前面加冒号(静默模式),则OPT被设置为
:
(如果此时没有:
匹配,则会匹配到?
)如果没加,则OPT被置为
?
case
最后一个选择——?,表示如果出现了选项列表之外的选项,进行的操作
OPTARG
表示当前选项的参数
OPTIND
表示下一个选项在【参数列表】中的位置,参数列表的初始值为1(即从$1开始)
处理带参数的选项,值加2;处理不带参数的选项或非法选项,值加1
在case匹配开始的时候就已经增加,指向了下一个参数的位置
shift
用来左移【参数列表】,shift 2 表示将参数列表中前2个左移(丢弃)
shift $(($OPTIND-?)) ,根据选项是否带参数灵活指定 ? 的值,可通过 $1 拿到想要的值
特点
-
Shell 内建命令
-
getopts不支持长选项。如 --help
-
输入选项参数的格式必须是
-o arg
参数紧跟选项,中间有空格 -
处理完一个选项后,OPTIND会自动指向下一个选项。
-
不会重排所有参数的顺序
-
带参数的选项要放在不带参数的选项(开关选项)之前,或者开关选项后面不能带参数
# 可以识别 -a 只是没有参数 lfp@legion:~$ ./bin/getopts.sh -a -b bb -c cc -d begin index is 1 begin ARG is $OPTIND=2, a is , $1=-a, $OPTIND=2 $OPTIND=4, b is bb, $2=-b, $OPTIND=4 $OPTIND=6, c is cc, $3=bb, $OPTIND=6 $OPTIND=7 剩余参数列表:-d Illegal option -- '-d', Usage: getopts.sh [-a] [-b arg] [-c arg] file ...
-
遇到非
-
开头的参数或选项结束标记--
,则终止# -- 选项结束 lfp@legion:~$ ./bin/getopts.sh -b bb -c cc -- -d -a begin index is 1 begin ARG is $OPTIND=3, b is bb, $2=bb, $OPTIND=3 $OPTIND=5, c is cc, $3=-c, $OPTIND=5 end index is 6 # 非 - 开头的参数 # 选项a不带参数,aa被识别为非-开头的参数 lfp@legion:~$ ./bin/getopts.sh -a aa -b bb -c cc -d begin index is 1 begin ARG is $OPTIND=2, a is , $1=-a, $OPTIND=2 end index is 2
-
遇到非法选项,则后面的选项参数都无法获取
# -d 非法选项 lfp@legion:~$ ./bin/getopts.sh -b bb -d -c cc -a begin index is 1 begin ARG is $OPTIND=3, b is bb, $2=bb, $OPTIND=3 ./bin/getopts.sh: 非法选项 -- d # 可以通过在选项列表字符串前面加冒号来取消 $OPTIND=4 剩余参数列表:-d -c cc -a Illegal option -- '-d', Usage: getopts.sh [-a] [-b arg] [-c arg] file ...
-
如果缺少参数
# 会把后面的 -c 选项当做参数,然后遇到 -c 选项的参数(非-开头的选项,终止) lfp@legion:~$ ./bin/getopts.sh -b -c cc -a begin index is 1 begin ARG is $OPTIND=3, b is -c, $2=-c, $OPTIND=3 end index is 3
-
如果选项和参数之间没有空格
lfp@legion:~$ ./bin/getopts.sh -bbb -c cc -a begin index is 1 begin ARG is # 可以拿到选项的值,但是 OPTIND 只加1,按无参数选项处理的 $OPTIND=2, b is bb, $2=-c, $OPTIND=2 $OPTIND=4, c is cc, $3=cc, $OPTIND=4 $OPTIND=5, a is , $1=-bbb, $OPTIND=5 end index is 5