如何实现命令行选项的各种个性功能
在前面命令行选项的那些事中介绍了几种有"个性"的选项功能,包括:
- 选项依赖:例如"-a"或"--add"要依赖于"-m"或"--manage"选项
- 选项互斥:例如"-a"或"--add"与"-r"或"--remove"是互斥的
- 识别负数参数:例如
-w -5 -3 5
,其中-5和-3不是短选项,而是负数参数 - 模式化选项:例如
script_name MODE OPTIONS
的MODE部分,可以是manage模式(--manage,-m),也可以使用add模式(--add,-a)
- 选项参数替代选项:例如
head -n 3
可以替换为head -3
这里介绍下用getopt解析参数后实现它们的思路。
在getopt解析完成后,假设返回结果保存到了$parameters
变量中。
1.选项依赖性
这个其实很好实现,只需使用grep对$parameters
变量进行筛选一下即可。
例如实现依赖性,只需:
{ echo "$parameters" | grep -E '\-\-add|\-a ' | grep -E '\-\-manage|\-m '; } &>/dev/null
[ $? -ne 0 ] && exit
2.选项互斥性
要实现互斥性,只需:
or_op=`echo "$parameters" | grep -Eo '\-\-add|\-a | \-\-remove|\-r ' | wc -l`
[ "$or_op" = "2" ] && exit
3.识别负数参数
前面解释过,getopt提供了两种扫描模式,只要使用+
扫描模式,就能轻松区别负数参数和短选项。
4.模式化选项
一般来说,模式化选项都是命令行的第一个参数。所以,只需将$parameter
中"--"后面的第一个非选项类型的参数提取出来,就是所谓的模式了。当然,还得对这个参数进行一些判断,避免它不是模式参数。
例如,要提供addr、show、route三种模式,那么其它的非选项类型参数值都不应该是模式参数。
eval set -- "$parameters"
while true ; do
case "$1" in
...
--)
shift
[ "$x" = "addr" -o "$x" = "route" -o "$x" = "show" ] && MODE=$1
shift
break ;;
*) echo "wrong";exit 1;;
esac
done
5.选项参数替代选项
就以-n3
和-3
为例,它的通用格式是-n NUM
和-NUM
。这个并不好实现,我能想到的方法是将这个-NUM
先从$@
中筛选出来,然后赋值。
NUM=`echo "$@" | grep -Eo "\-[0-9]+"`
ARGS=`echo "$@" | sed -nr 's!(.*)-[0-9]+(.*)!\1\2!'p`
eval set -- "$ARGS"