首页 > 代码库 > 使用getopt处理shell脚本的参数

使用getopt处理shell脚本的参数

getopt命令并不是bash的内建命令,它是由util-linux包提供的外部命令。相比较bash 的内置命令,getopt不只支持短参-s,还支持--longopt的长参数,甚至支持-longopt的简化参数。getopt可以用于tcsh其它的shell。
现在就以系统自带的帮助文件,说说getopt在bash下的使用技巧。
 
#!/bin/bash  
 
# A small example program for using the new getopt(1) program.  
# This program will only work with bash(1)  
# An similar program using the tcsh(1) script language can be found  
# as parse.tcsh  
 
# Example input and output (from the bash prompt):  
# ./parse.bash -a par1 ‘another arg‘ --c-long ‘wow!*\?‘ -cmore -b " very long "  
# Option a  
# Option c, no argument  
# Option c, argument `more‘  
# Option b, argument ` very long ‘  
# Remaining arguments:  
# --> `par1‘  
# --> `another arg‘  
# --> `wow!*\?‘  
 
# Note that we use `"$@"‘ to let each command-line parameter expand to a   
# separate word. The quotes around `$@‘ are essential!  
# We need TEMP as the `eval set --‘ would nuke the return value of getopt.  
TEMP=`getopt -o ab:c:: --long a-long,b-long:,c-long:: \  
     -n ‘example.bash‘ -- "$@"`  
 
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi  
 
# Note the quotes around `$TEMP‘: they are essential!  
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)  
                        # c has an optional argument. As we are in quoted mode,  
                        # an empty parameter will be generated if its optional  
                        # argument is not found.  
                        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 
 getopt 命令的选项说明:
-a 使getopt长参数支持"-"符号打头,必须与-l同时使用
-l 后面接getopt支持长参数列表
-n program如果getopt处理参数返回错误,会指出是谁处理的这个错误,这个在调用多个脚本时,很有用
-o 后面接短参数列表,这种用法与getopts类似
-u 不给参数列表加引号,默认是加引号的(不使用-u选项),例如在加不引号的时候 --longopt "select * from db1.table1" $2只会取到select ,而不是完整的SQL语句。
使用eval 的目的是为了防止参数中有shell命令,被错误的扩展。
实际官方提供的这个语法也不是很简洁,下面提供一个我平时用到的:
 
ARGS=`getopt -a -o I:D:T:e:k:LMSsth -l instence:,database:,table:,excute:,key:,list,master,slave,status,tableview,help -- "$@"`   ###在参数列表做后加入 --
[ $? -ne 0 ] && usage  
#set -- "${ARGS}"  
eval set -- "${ARGS}"                                                    ####这句不可少    ### 长的参数选项最好用=指定 如 --port=22 | ./configure --prefix=/usr/local
 
while true  
do  
        case "$1" in 
        -I|--instence)  
                instence="$2" 
                shift  
                ;;  
        -D|--database)  
                database="$2" 
                shift  
                ;;  
        -T|--table)  
                table="$2" 
                shift  
                ;;  
        -e|--excute)  
                excute="yes" 
                shift  
                ;;  
        -k|--key)  
                key="$2" 
                shift  
                ;;  
        -L|--list)  
                LIST="yes" 
                ;;  
        -M|--master)  
                MASTER="yes" 
                ;;  
        -S|--slave)  
                SLAVE="yes" 
                ;;  
        -A|--alldb)  
                ALLDB="yes" 
                ;;  
        -s|--status)  
                STATUS="yes" 
                ;;  
        -t|--tableview)  
                TABLEVIEW="yes" 
                ;;  
        -h|--help)  
                usage  
                ;;  
        --)  
                shift  
                break 
                ;;  
        esac  
shift  
done 
重点关注一下,esac和done中的shift,还有符号“--”条件下的shift;break操作。










#############################################################################################################################
 bash环境下,以“-”或“--”开头的参数称选项参数。可以使用bash内置命令getopts或外部命令getopt进行传递。getopts的时候可参考《》,以下用getopt的范例进行说明。
一、获取范例
getopt官网:点击
范例下载:
下载文件
点击这里下载文件


二、前提
1、先确定是否增强版的getopt
引用
# getopt -T
# echo $?
4
# getopt -V
getopt (enhanced) 1.1.3


返回结果为4,则为增强版的getopt,否则为旧版本。
2、命令参数
getopt可以为bash提供短选项和长选项的参数引用:
引用
-o 短选项
-l 长选项
-n 脚本命令,若传递参数报错,会报该名字


选项的使用定义规则类似:
引用
ab:c::


意思是:
引用
a 后没有冒号,表示没有可以参数
b 后跟一个冒号,表示有一个必要的参数
c 后跟两个冒号,表示有一个可选的参数
长选项的定义相同,但用逗号分割。




三、示例脚本
截取主要部分:
引用


# 请注意定义方法,以及使用"$@"从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必须使用“"”号括住
eval set -- "$TEMP"


#请留意shift需根据是否可接受参数而移动
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) 
     # c 选项带一个可选的参数,若没有指定则为空,请留意后面给予选项参数的写法
     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、第一次
引用
# sh getopt-parse.bash -a "arg1 arg2"
Option a
Remaining arguments:
--> `arg1 arg2‘


可以看到,-a后不能接受选项参数,其会作为普通参数存在。
2、第二次
引用
# sh getopt-parse.bash -b "arg4"
Option b, argument `arg4‘
Remaining arguments:


-b选项可以接受参数。再试试这个:
引用
# sh getopt-parse.bash -b
example.bash:选项需要一个参数 -- b
Remaining arguments:


-b后面跟的是必要参数哦,不能忽略。
3、第三次
引用
# sh getopt-parse.bash -c "arg3"
Option c, no argument
Remaining arguments:
--> `arg3‘


奇怪,-c后已经跟有选项参数,但并没有识别到?再试试:
引用
# sh getopt-parse.bash -c"arg3"
Option c, argument `arg3‘
Remaining arguments:


原来如此,-c和选项参数之间不能有空格。
4、全部一起
引用
# sh getopt-parse.bash -a "arg1 arg2" -c"arg3" -b "arg4" "arg5"
Option a
Option c, argument `arg3‘
Option b, argument `arg4‘
Remaining arguments:
--> `arg1 arg2‘
--> `arg5‘


请注意区分选项参数和普通参数。


五、遗留问题
   长选项使用可选参数会报错,可见:
引用
# sh getopt-parse.bash -c"more"
Option c, argument `more‘
Remaining arguments:
# sh getopt-parse.bash --c-long"more"
example.bash:无法识别的选项“--c-longmore”
Remaining arguments:
# sh getopt-parse.bash --c-long "more"
Option c, no argument
Remaining arguments:
--> `more‘






################################################################
1.单个字符,表示选项,
2.单个字符后接一个冒号:表示该选项后必须跟一个参数。参数在选项后空格隔开。该参数的指针赋给optarg。
3 单个字符后跟两个冒号,表示该选项后非必需跟一个参数。若有参数必须紧跟在选项后不能以空格隔开。该参数的指针赋给optarg。(这个特性是GNU的扩张)。
getopt处理以‘-’开头的命令行参数,如optstring="ab:c::d::",命令行为getopt.exe -a -b host -ckeke -d haha 
在这个命令行参数中,-a和-h就是选项元素,去掉‘-‘,a,b,c就是选项。host是b的参数,keke是c的参数。但haha并不是d的参数,因为它们中间有空格隔开。
还要注意的是默认情况下getopt会重新排列命令行参数的顺序,所以到最后所有不包含选项的命令行参数都排到最后。

本文出自 “我是一只小小鸟” 博客,请务必保留此出处http://2242558.blog.51cto.com/2232558/1545331

使用getopt处理shell脚本的参数