./myscript.sh -a -b arg
在脚本中通常是用case语句处理。我个人比较喜欢的做法:首先尽量使用长参数名(短参数名通常意义不明显,毕竟你的脚本没有这么流行),比如
./myscript --with-ssl=yes --install-dir=../export
再在脚本中通过下面的函数处理参数
################################################################################ # 分析命令行,如果命令行中有选项(作为函数第1个实参): # --xxx-x-x=vvv # 则这个函数执行__xxx_x_x=vvv,即,相当于将vvv赋值给__xxx_x_x变量 # 如果命令行中的选项不包含'='号,则这个函数将命令行参数插入第2个实参代表的变量中 # 以供稍后处理 ################################################################################ function ParseOption(){ if [ $# -gt 0 ]; then if [ "${1:0:2}" = "--" ]; then local key=${1%%=*} if [ "${key}" != "${1}" ]; then local value=${1#*=} key=${key//-/_} eval ${key}=${value} return 0 elif [ -n "${key}" ] && [ -n "${2}" ]; then eval ${2}+=\" ${1}\" return 0 else return 1 fi elif [ -n "${2}" ]; then eval ${2}+=\" ${1}\" return 0 else return 1 fi else return 1 fi } arguments= for option in $* do ParseOption ${option} arguments done
arguments可以稍后拿来做case处理,但对于赋值型命令行参数,这种处理方式扩展性非常好。
比如,我们的脚本要跟svn打交道,有下面的语句:
svn update
但我在其它机器上运行这个脚本时,发现它的svn没有安装在系统路径,需要使用全路径引用。我只需要简单的修改这行代码为
${__svn:-svn} update
不用添加任何多余的代码,脚本就可以支持通过命令行参数的方式指定svn路径,即
./myscript --svn=/opt/subversion/bin/svn ...
相当方便。通过这种方式,添加命令行参数的支持不再麻烦,脚本只需要正确使用变量即可。
另外,一些“动态命名”的参数,用case也难以处理,如
./build-tool ... --platforms=st5197,st7105 --st5197-config=st5197_setenv.sh --st7105-config=st7105_setenv.sh上述命令的意思是,我们的平台指定了st5197和st7105,同时,这两个平台都有预处理脚本,在我们的进行正式工作前要去执行(比如说一些环境变量的设置)。这些脚本的数量不定(对应于--platforms指定的平台数),就是说,--platforms指定了4个平台,后面可能会有4个--{platform}-config(也可能少于4个,表明相应平台不需要预处理脚本);同时,指定的这些参数要能够与相应的平台联系起来,这就是为什么我们在选项命名上与平台关联起来(也就是说,这些选项命名不是预先确定的)。
for platform in ${__platforms} do #如果命令行指定了参数--{platform}-config=FILE,则在上述ParseOption()里__{platform}_config变量已被赋上值,将这个值转存到platform_config变量里以方便后面引用 eval platform_config='$'__${platform}_config if [ -n "${platform_config}" ]; then ... fi done可以简单的获取平台对应的config文件名称,并加以处理。