shell 脚本里更好命令行参数
Table of Contents
我们经常需要在脚本中获取命令行参数,而 getopts 就是实现解析命令行参数 的可靠工具,但也有它的局限性。
1 getopts
在频繁使用的小脚本中,getopts 可以说是完美的选择,它可以让你写更少的代 码:
paste=vpaste # default is vertical pasting
seplist="\t" # default separator is tab
while getopts d:s o
do case "$o" in
d) seplist="$OPTARG";;
s) paste=hpaste;;
[?]) print >&2 "Usage: $0 [-s] [-d seplist] file ..."
exit 1;;
esac
done
shift $OPTIND-1
# perform actual paste command
$paste -d "$seplist" "$@"
上述程序接受两个可选参数,-d xxx 和=-s,程序中把 xxx 保存 在变量 seplist 中;如果指定了 -s 选项,则变量 paste=hpaste, (默认是 vpasste)。
这么做虽然简单,但很快,你会忘记 -abc 到底是什么意思,而你的同事也 会反复问你 -d 后面应该填什么。而且在功能复杂的脚本中,26个字母很快 就会用完。这时候就需要自己解析命令行参数了。
2 目标
我们希望脚本可以接受类似 −−var−a=xxx−−var−a=xxx 和 −−enable−feature−c−−enable−feature−c 的 参数。一般的,需要设置一个 −−help−−help 参数,如果被指定则打印每个参数的 用途。
这只是一个脚本程序,我们希望它尽量简单明了,不需要太多的抽象。对脚本文 件而言,“一把梭”可能是就是最好的。你的同事已经在主要功能上花费了太多的 精力,当他以为已经完成了所有工作的时候,你告诉他有一个辅助脚本需要添加 一个参数,为了添加这个参数需要理解其中复杂的逻辑,那就太令人绝望了。所 以脚本应该让人看一眼就知道怎么修改,并且没有任何低估。因为是“一把梭”, 我认为中间过程是没有必要的,所以代码就像这样:
3 示例代码
# 设置一些变量的默认值
# 这些变量用于保存命令行参数的解析结果
help=no
VAR_A=
VAR_B=
HAVE_FEATURE_C=NO
# for 循环遍历命令行参数,参数使用空格隔开
for option
do
# 获得参数的值,保存到变量 $value 中
case "$option" in
-*=*) value=`echo "$option" | sed -e 's/[-_a-zA-Z0-9]*=//'` ;;
*) value="" ;;
esac
# 枚举接受的命令行参数,逐一处理,根据参数对最开始的变量赋值
case "$option" in
--help) help=yes ;;
--var-a=*) VAR_A="$value" ;;
--var-b=*) VAR_B="$value" ;;
--have-feature-c) HAVE_FEATURE_C=YES ;;
# ...
*)
echo "$0: error: invalid option \"$option\""
exit 1
;;
esac
done
# 打印帮助信息
if [ $help = yes ]; then
cat << END
--help print this message
--var-a=ARG set var-a ...
--var-b=ARG est var-b ...
--have-feature-c enaable feature C
...
END
exit 1
fi
# 如果参数为空,设置一些默认值,这是可选的
VAR_A=${VAR_A:-default_value1}
# ...
# 现在可以使用这些表示命令行参数的变量了
echo "VAR_A=$VAR_A; VAR_B=$VAR_B; HAVE_FEATURE_C=$HAVE_FEATURE_C"
# ...