在Shell脚本中处理命令行参数

来源:互联网 发布:mac虚拟机内存 编辑:程序博客网 时间:2024/05/24 05:03
运行脚本时的命令行参数,如
./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} argumentsdone

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个,表明相应平台不需要预处理脚本);同时,指定的这些参数要能够与相应的平台联系起来,这就是为什么我们在选项命名上与平台关联起来(也就是说,这些选项命名不是预先确定的)。
在Shell脚本中,可以对上面的参数做如下处理
for platform in ${__platforms}do    #如果命令行指定了参数--{platform}-config=FILE,则在上述ParseOption()里__{platform}_config变量已被赋上值,将这个值转存到platform_config变量里以方便后面引用    eval platform_config='$'__${platform}_config    if [ -n "${platform_config}" ]; then        ...    fidone
可以简单的获取平台对应的config文件名称,并加以处理。