Using getopts to process long and short command line options

后端 未结 30 1585
佛祖请我去吃肉
佛祖请我去吃肉 2020-11-21 22:52

I wish to have long and short forms of command line options invoked using my shell script.

I know that getopts can be used, but like in Perl, I have not

30条回答
  •  日久生厌
    2020-11-21 23:21

    Builtin getopts only parse short options (except in ksh93), but you can still add few lines of scripting to make getopts handles long options.

    Here is a part of code found in http://www.uxora.com/unix/shell-script/22-handle-long-options-with-getopts

      #== set short options ==#
    SCRIPT_OPTS=':fbF:B:-:h'
      #== set long options associated with short one ==#
    typeset -A ARRAY_OPTS
    ARRAY_OPTS=(
        [foo]=f
        [bar]=b
        [foobar]=F
        [barfoo]=B
        [help]=h
        [man]=h
    )
    
      #== parse options ==#
    while getopts ${SCRIPT_OPTS} OPTION ; do
        #== translate long options to short ==#
        if [[ "x$OPTION" == "x-" ]]; then
            LONG_OPTION=$OPTARG
            LONG_OPTARG=$(echo $LONG_OPTION | grep "=" | cut -d'=' -f2)
            LONG_OPTIND=-1
            [[ "x$LONG_OPTARG" = "x" ]] && LONG_OPTIND=$OPTIND || LONG_OPTION=$(echo $OPTARG | cut -d'=' -f1)
            [[ $LONG_OPTIND -ne -1 ]] && eval LONG_OPTARG="\$$LONG_OPTIND"
            OPTION=${ARRAY_OPTS[$LONG_OPTION]}
            [[ "x$OPTION" = "x" ]] &&  OPTION="?" OPTARG="-$LONG_OPTION"
    
            if [[ $( echo "${SCRIPT_OPTS}" | grep -c "${OPTION}:" ) -eq 1 ]]; then
                if [[ "x${LONG_OPTARG}" = "x" ]] || [[ "${LONG_OPTARG}" = -* ]]; then 
                    OPTION=":" OPTARG="-$LONG_OPTION"
                else
                    OPTARG="$LONG_OPTARG";
                    if [[ $LONG_OPTIND -ne -1 ]]; then
                        [[ $OPTIND -le $Optnum ]] && OPTIND=$(( $OPTIND+1 ))
                        shift $OPTIND
                        OPTIND=1
                    fi
                fi
            fi
        fi
    
        #== options follow by another option instead of argument ==#
        if [[ "x${OPTION}" != "x:" ]] && [[ "x${OPTION}" != "x?" ]] && [[ "${OPTARG}" = -* ]]; then 
            OPTARG="$OPTION" OPTION=":"
        fi
    
        #== manage options ==#
        case "$OPTION" in
            f  ) foo=1 bar=0                    ;;
            b  ) foo=0 bar=1                    ;;
            B  ) barfoo=${OPTARG}               ;;
            F  ) foobar=1 && foobar_name=${OPTARG} ;;
            h ) usagefull && exit 0 ;;
            : ) echo "${SCRIPT_NAME}: -$OPTARG: option requires an argument" >&2 && usage >&2 && exit 99 ;;
            ? ) echo "${SCRIPT_NAME}: -$OPTARG: unknown option" >&2 && usage >&2 && exit 99 ;;
        esac
    done
    shift $((${OPTIND} - 1))
    

    Here is a test:

    # Short options test
    $ ./foobar_any_getopts.sh -bF "Hello world" -B 6 file1 file2
    foo=0 bar=1
    barfoo=6
    foobar=1 foobar_name=Hello world
    files=file1 file2
    
    # Long and short options test
    $ ./foobar_any_getopts.sh --bar -F Hello --barfoo 6 file1 file2
    foo=0 bar=1
    barfoo=6
    foobar=1 foobar_name=Hello
    files=file1 file2
    

    Otherwise in recent Korn Shell ksh93, getopts can naturally parse long options and even display a man page alike. (See http://www.uxora.com/unix/shell-script/20-getopts-with-man-page-and-long-options)

提交回复
热议问题