getopts的使用
语法格式:getopts [option[:]] [DESCPRITION] VARIABLE
option:表示为某个脚本可以使用的选项
":":如果某个选项(option)后面出现了冒号(":"),则表示这个选项后面可以接参数(即一段描述信息DESCPRITION)
VARIABLE:表示将某个选项保存在变量VARIABLE中
getopts是linux系统中的一个内置变量,一般用在循环中。每当执行循环是,getopts都会检查下一个命令选项,如果这些选项出现在option中,则表示是合法选项,否则不是合法选项。并将这些合法选项保存在VARIABLE这个变量中。
getopts还包含两个内置变量,及OPTARG和OPTIND
OPTARG就是将选项后面的参数(或者描述信息DESCPRITION)保存在这个变量当中。
OPTIND:这个表示命令行的下一个选项或参数的索引(文件名不算选项或参数)
#!/bin/bashwhile getopts ':b:d:' OPT &> /dev/null;do
case $OPT in
b)
echo "The options is b"
echo $OPTARG ;;
d)
echo "The options is d"
echo $OPTARG ;;
*)
echo "Wrong Options"
exit 7 ;;
esac
# echo $OPT
# echo $OPTARG
done
echo $OPTIND
shift $[$OPTIND-1]
echo $1
###执行脚本时,显示的结果如下###
[root@localhost scriptTEAM]# ./test -d 'nice' fixnale
The options is d
nice
3
fixnale
###显示信息说明如下###
当输入-d时,$OPT=d,$OPTARG='nice',因此就会显示d)...这一部分的信息。
由于这里有一个选项(-d)和一个参数('nice'),$OPTIND指向命令行中下一个选项或参数的索引位置,因此这里即为3。
shift $[$OPTIND-1]表示将文件名前面的选项和参数踢掉
getopts参数的使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | [root@localhost ~]
echo $*
while getopts ":a:bc:" opt
do
case $opt in
a)
echo $OPTARG $OPTIND;;
b)
echo "b $OPTIND" ;;
c)
echo "c $OPTIND" ;;
?)
echo "error"
exit 1;;
esac
done
echo $OPTIND
shift $(( $OPTIND-1 ))
echo $0
echo $*
|
执行结果如下:
1 2 3 4 5 6 7 | [root@localhost ~]
-a 11 -b -c 6
11 3
b 4
c 6
6
getopts .sh
|
为什么会得到上面的结果呢?
while getopts ":a:bc:" opt #第一个冒号表示忽略错误;字符后面的冒号表示该选项必须有自己的参数。
$optarg 存储相应选项的参数,如上例中的11、6;
$optind 总是存储原始$*中下一个要处理的选项(不是参数,而是选项,此处指的是a,b,c这三个选项,而不是那些数字,当然数字也是会占有位置的)位置。
optind初值为1,遇到"x",选项不带参数,optind+=1;遇到"x:",带参数的选项,optarg=argv[optind+1],optind+=2;遇到"x::",可选参数,属于#1和#2之一(转载过来的,这句我也看不懂)
第一行输出echo $*
第二行,optind初值为1,选项-a的参数为11,下一个要处理的选项-b位置为3,所以输出:11 3;
第三行,然后-b要处理的下一个选项-c位置为4,所以输出:b 4;
第四行,再者-c有参数,所以下一个要处理的位置+2,所以输出:c 6;
自己随手输入的例子:
1 2 3 4 5 6 7 8 | [root@localhost ~]
-a 11 -b -b 5 -c 6
11 3
b 4
b 5
5
getopts .sh
9 -c 6
|
起初我看到以上的输出结果百思不得其解,后面多试几次选项及参数后,大概猜了一下。
第一行输出echo $*
第二行,optind初值为1,下一个要处理的选项-b位置为3,所以输出11 3;
第三行,下一个要处理的选项-b位置为4,所以输出b 4;
第四行,下一个要处理的选项-b位置为5,所以输出b 5;
程序现在遇到9,不属于getopts,所以停止循环while,下面几行就不解释了。
getopt
与 getopts
都是 Bash 中用来获取与分析命令行参数的工具,常用在 Shell 脚本中被用来分析脚本参数。
两者的比较
(1)getopts 是 Shell 内建命令,getopt 是一个独立外部工具
(2)getopts 使用语法简单,getopt 使用语法较复杂
(3)getopts 不支持长参数(如:--option
),getopt 支持
(4)getopts 不会重排所有参数的顺序,getopt 会重排参数顺序(这里的区别下面会说明)
(5)getopts 出现的目的是为了代替 getopt 较快捷的执行参数分析工作
1 getopts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | #!/bin/bash
while getopts 'd:Dm:f:t:' OPT; do
case $OPT in
d)
DEL_DAYS= "$OPTARG" ;;
D)
DEL_ORIGINAL= 'yes' ;;
f)
DIR_FROM= "$OPTARG" ;;
m)
MAILDIR_NAME= "$OPTARG" ;;
t)
DIR_TO= "$OPTARG" ;;
?)
echo "Usage: `basename $0` [options] filename"
esac
done
shift $(($OPTIND - 1))
|
getopts后面的字符串就是可以使用的选项列表,每个字母代表一个选项,后面带:的意味着选项除了定义本身之外,还会带上一个参数作为选项的值,比如d:在实际的使用中就会对应-d 30,选项的值就是30;getopts字符串中没有跟随:的是开关型选项,不需要再指定值,相当于true/false,只要带了这个参数就是true。如果命令行中包含了没有在getopts列表中的选项,会有警告信息,如果在整个getopts字符串前面也加上个:,就能消除警告信息了。
使用getopts识别出各个选项之后,就可以配合case来进行相应的操作了。操作中有两个相对固定的“常量”,一个是OPTARG,用来取当前选项的值,另外一个是OPTIND,代表当前选项在参数列表中的位移。注意case中的最后一个选择──?,代表这如果出现了不认识的选项,所进行的操作。
选项参数识别完成之后,如果要取剩余的其它命令行参数,可以使用shift把选项参数抹去,就像例子里面的那样,对整个参数列表进行左移操作,最左边的参数就丢失了(已经用case判断并进行了处理,不再需要了),位移的长度正好是刚才case循环完毕之后的OPTIND - 1,因为参数从1开始编号,选项处理完毕之后,正好指向剩余其它参数的第一个。在这里还要知道,getopts在处理参数的时候,处理一个开关型选项,OPTIND加1,处理一个带值的选项参数,OPTIND则会加2。
最后,真正需要处理的参数就是1 1 #了,可以用for循环依次处理。
使用getopts处理参数虽然是方便,但仍然有两个小小的局限:
1.选项参数的格式必须是-d val,而不能是中间没有空格的-dval。
2.所有选项参数必须写在其它参数的前面,因为getopts是从命令行前面开始处理,遇到非-开头的参数,或者选项参数结束标记--就中止了,如果中间遇到非选项的命令行参数,后面的选项参数就都取不到了。
3.不支持长选项, 也就是--debug之类的选项
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #!/bin/bash
echo 初始 OPTIND: $OPTIND
while getopts "a:b:c" arg
do
case $arg in
a)
echo "a's arg:$OPTARG"
;;
b)
echo "b's arg:$OPTARG"
;;
c)
echo "c's arg:$OPTARG"
;;
?)
echo "unkonw argument"
exit 1
;;
esac
done
echo 处理完参数后的 OPTIND:$OPTIND
echo 移除已处理参数个数:$((OPTIND-1))
shift $((OPTIND-1))
echo 参数索引位置:$OPTIND
echo 准备处理余下的参数:
echo "Other Params: $@"
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | june@Win7 192.168.1.111 02:32:45 ~ >
bash b.sh -a 1 -b 2 -c 3 test -oo xx - test
初始 OPTIND: 1
a's arg:1
b's arg:2
c's arg:
处理完参数后的 OPTIND:6
移除已处理参数个数:5
参数索引位置:6
准备处理余下的参数:
Other Params: 3 test -oo xx - test
june@Win7 192.168.1.111 02:32:49 ~ >
bash b.sh -a 1 -c 3 -b 2 test -oo xx - test
初始 OPTIND: 1
a's arg:1
c's arg:
处理完参数后的 OPTIND:4
移除已处理参数个数:3
参数索引位置:4
准备处理余下的参数:
Other Params: 3 -b 2 test -oo xx - test
june@Win7 192.168.1.111 02:33:14 ~ >
bash b.sh -a 1 -c -b 2 test -oo xx - test
初始 OPTIND: 1
a's arg:1
c's arg:
b's arg:2
处理完参数后的 OPTIND:6
移除已处理参数个数:5
参数索引位置:6
准备处理余下的参数:
Other Params: test -oo xx - test
june@Win7 192.168.1.111 02:33:22 ~ >
|
2 getopt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | Code highlighting produced by Actipro CodeHighlighter (freeware)http: //www .CodeHighlighter.com /-- >
#!/bin/bash TEMP=`getopt -o ab:c:: --long a-long,b-long:,c-long:: \
-n 'example.bash' -- "$@" ` if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi eval set -- "$TEMP" while true ; do
case "$1" in
-a|--a-long) echo "Option a" ; shift ;;
-b|--b-long) echo "Option b, argument \`$2'" ; shift 2 ;;
-c|--c-long)
case "$2" in
"" ) echo "Option c, no argument" ; shift 2 ;;
*) echo "Option c, argument \`$2'" ; shift 2 ;;
esac ;;
--) shift ; break ;;
*) echo "Internal error!" ; exit 1 ;;
esac
done
echo "Remaining arguments:"
for arg do
echo '--> ' "\`$arg'" ;
done
|
一个例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #!/bin/bash ARGS=`getopt -o "ao:" -l "arg,option:" -n "getopt.sh" -- "$@" ` eval set -- "${ARGS}" while true ; do
case "${1}" in
-a|--arg)
shift ;
echo -e "arg: specified"
;;
-o|--option)
shift ;
if [[ -n "${1}" ]]; then
echo -e "option: specified, value is ${1}"
shift ;
fi
;;
--)
shift ;
break ;
;;
esac
done
|
1 2 3 4 5 6 7 8 | arg: specified
arg: specified
option: specified, value is Apple
arg: specified
option: specified, value is Apple
|