zoukankan      html  css  js  c++  java
  • Shell 参数(2) --解析命令行参数工具:getopts/getopt

    getopt 与 getopts 都是 Bash 中用来获取与分析命令行参数的工具,常用在 Shell 脚本中被用来分析脚本参数。

    两者的比较

    (1)getopts 是 Shell 内建命令,getopt 是一个独立外部工具

    (2)getopts 使用语法简单,getopt 使用语法较复杂

    (3)getopts 不支持长参数(如:--option ),getopt 支持

    (4)getopts 不会重排所有参数的顺序,getopt 会重排参数顺序(这里的区别下面会说明)

    (5)getopts 出现的目的是为了代替 getopt 较快捷的执行参数分析工作

    1 getopts

    #!/bin/bash
    while getopts 'd:Dm:f:t:' OPT; do
        case $OPT in
            d)
                DEL_DAYS="$OPTARG";;
            D)
                DEL_ORIGINAL='yes';;
            f)
                DIR_FROM="$OPTARG";;
            m)
                MAILDIR_NAME="$OPTARG";;
            t)
                DIR_TO="$OPTARG";;
            ?)
                echo "Usage: `basename $0` [options] filename"
        esac
    done
     
    shift $(($OPTIND - 1))
    

      

    getopts后面的字符串就是可以使用的选项列表,每个字母代表一个选项,后面带:的意味着选项除了定义本身之外,还会带上一个参数作为选项的值,比如d:在实际的使用中就会对应-d 30,选项的值就是30;getopts字符串中没有跟随:的是开关型选项,不需要再指定值,相当于true/false,只要带了这个参数就是true。如果命令行中包含了没有在getopts列表中的选项,会有警告信息,如果在整个getopts字符串前面也加上个:,就能消除警告信息了。

    使用getopts识别出各个选项之后,就可以配合case来进行相应的操作了。操作中有两个相对固定的“常量”,一个是OPTARG,用来取当前选项的值,另外一个是OPTIND,代表当前选项在参数列表中的位移。注意case中的最后一个选择──?,代表这如果出现了不认识的选项,所进行的操作。 

    选项参数识别完成之后,如果要取剩余的其它命令行参数,可以使用shift把选项参数抹去,就像例子里面的那样,对整个参数列表进行左移操作,最左边的参数就丢失了(已经用case判断并进行了处理,不再需要了),位移的长度正好是刚才case循环完毕之后的OPTIND - 1,因为参数从1开始编号,选项处理完毕之后,正好指向剩余其它参数的第一个。在这里还要知道,getopts在处理参数的时候,处理一个开关型选项,OPTIND加1,处理一个带值的选项参数,OPTIND则会加2。 

    最后,真正需要处理的参数就是$1~$#了,可以用for循环依次处理。

    使用getopts处理参数虽然是方便,但仍然有两个小小的局限:

    1.选项参数的格式必须是-d val,而不能是中间没有空格的-dval。
    2.所有选项参数必须写在其它参数的前面,因为getopts是从命令行前面开始处理,遇到非-开头的参数,或者选项参数结束标记--就中止了,如果中间遇到非选项的命令行参数,后面的选项参数就都取不到了。
    3.不支持长选项, 也就是--debug之类的选项

    #!/bin/bash
    echo 初始 OPTIND: $OPTIND
     
    while getopts "a:b:c" arg #选项后面的冒号表示该选项需要参数
    do
        case $arg in
            a)
                echo "a's arg:$OPTARG" #参数存在$OPTARG中
                ;;
            b)
                echo "b's arg:$OPTARG"
                ;;
            c)
                echo "c's arg:$OPTARG"
                ;;
            ?)  #当有不认识的选项的时候arg为?
                echo "unkonw argument"
                exit 1
            ;;
        esac
    done
     
    echo 处理完参数后的 OPTIND:$OPTIND
    echo 移除已处理参数个数:$((OPTIND-1))
    shift $((OPTIND-1))
    echo 参数索引位置:$OPTIND
    echo 准备处理余下的参数:
    echo "Other Params: $@"
    

      

    june@Win7 192.168.1.111 02:32:45 ~ >
    bash b.sh -a 1 -b 2 -c 3  test -oo xx -test
    初始 OPTIND: 1
    a's arg:1
    b's arg:2
    c's arg:
    处理完参数后的 OPTIND:6
    移除已处理参数个数:5
    参数索引位置:6
    准备处理余下的参数:
    Other Params: 3 test -oo xx -test
    june@Win7 192.168.1.111 02:32:49 ~ >
    bash b.sh -a 1 -c 3 -b 2 test -oo xx -test   # 非参数选项注意顺序与值,不要多传
    初始 OPTIND: 1
    a's arg:1
    c's arg:
    处理完参数后的 OPTIND:4
    移除已处理参数个数:3
    参数索引位置:4
    准备处理余下的参数:
    Other Params: 3 -b 2 test -oo xx -test
    june@Win7 192.168.1.111 02:33:14 ~ >
    bash b.sh -a 1 -c -b 2 test -oo xx -test
    初始 OPTIND: 1
    a's arg:1
    c's arg:
    b's arg:2
    处理完参数后的 OPTIND:6
    移除已处理参数个数:5
    参数索引位置:6
    准备处理余下的参数:
    Other Params: test -oo xx -test
    june@Win7 192.168.1.111 02:33:22 ~ >
    

     

    2 getopt

    Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->
    #!/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.
    
    #-o表示短选项,两个冒号表示该选项有一个可选参数,可选参数必须紧贴选项
    #如-carg 而不能是-c arg
    #--long表示长选项
    #"$@"在上面解释过
    # -n:出错时的信息
    # -- :举一个例子比较好理解:
    #我们要创建一个名字为 "-f"的目录你会怎么办?
    # mkdir -f #不成功,因为-f会被mkdir当作选项来解析,这时就可以使用
    # mkdir -- -f 这样-f就不会被作为选项。
    
    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!
    #set 会重新排列参数的顺序,也就是改变$1,$2...$n的值,这些值在getopt中重新排列过了
    eval set -- "$TEMP"
    
    #经过getopt的处理,下面处理具体选项。
    
    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
    

     一个例子

    #!/bin/bash
    
    ARGS=`getopt -o "ao:" -l "arg,option:" -n "getopt.sh" -- "$@"`
    
    eval set -- "${ARGS}"
    
    while true; do
        case "${1}" in
            -a|--arg)
            shift;
            echo -e "arg: specified"
            ;;
            -o|--option)
            shift;
            if [[ -n "${1}" ]]; then
                echo -e "option: specified, value is ${1}"
                shift;
            fi
            ;;
            --)
            shift;
            break;
            ;;
        esac
    done
    

      

    # ./getopt.sh -a
    arg: specified
    # ./getopt.sh -a -o Apple
    arg: specified
    option: specified, value is Apple
    # ./getopt.sh --arg --option Apple
    arg: specified
    option: specified, value is Apple
    

     

    参考文章

    http://hiaero.net/getopts-versus-getopt/

    http://my.oschina.net/leejun2005/blog/202376

    http://www.cnblogs.com/xupeizhi/archive/2013/02/18/2915659.html

  • 相关阅读:
    创建Variant数组
    ASP与存储过程(Stored Procedures)
    FileSystemObject对象成员概要
    Kotlin 朱涛9 委托 代理 懒加载 Delegate
    Kotlin 朱涛 思维4 空安全思维 平台类型 非空断言
    Kotlin 朱涛7 高阶函数 函数类型 Lambda SAM
    Kotlin 朱涛16 协程 生命周期 Job 结构化并发
    Proxy 代理模式 动态代理 cglib MD
    RxJava 设计理念 观察者模式 Observable lambdas MD
    动态图片 Movie androidgifdrawable GifView
  • 原文地址:https://www.cnblogs.com/yxzfscg/p/5338775.html
Copyright © 2011-2022 走看看