Using getopts to process long and short command line options

后端 未结 30 1604
佛祖请我去吃肉
佛祖请我去吃肉 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:14

    The Bash builtin getopts function can be used to parse long options by putting a dash character followed by a colon into the optspec:

    #!/usr/bin/env bash 
    optspec=":hv-:"
    while getopts "$optspec" optchar; do
        case "${optchar}" in
            -)
                case "${OPTARG}" in
                    loglevel)
                        val="${!OPTIND}"; OPTIND=$(( $OPTIND + 1 ))
                        echo "Parsing option: '--${OPTARG}', value: '${val}'" >&2;
                        ;;
                    loglevel=*)
                        val=${OPTARG#*=}
                        opt=${OPTARG%=$val}
                        echo "Parsing option: '--${opt}', value: '${val}'" >&2
                        ;;
                    *)
                        if [ "$OPTERR" = 1 ] && [ "${optspec:0:1}" != ":" ]; then
                            echo "Unknown option --${OPTARG}" >&2
                        fi
                        ;;
                esac;;
            h)
                echo "usage: $0 [-v] [--loglevel[=]]" >&2
                exit 2
                ;;
            v)
                echo "Parsing option: '-${optchar}'" >&2
                ;;
            *)
                if [ "$OPTERR" != 1 ] || [ "${optspec:0:1}" = ":" ]; then
                    echo "Non-option argument: '-${OPTARG}'" >&2
                fi
                ;;
        esac
    done
    

    After copying to executable file name=getopts_test.sh in the current working directory, one can produce output like

    $ ./getopts_test.sh
    $ ./getopts_test.sh -f
    Non-option argument: '-f'
    $ ./getopts_test.sh -h
    usage: code/getopts_test.sh [-v] [--loglevel[=]]
    $ ./getopts_test.sh --help
    $ ./getopts_test.sh -v
    Parsing option: '-v'
    $ ./getopts_test.sh --very-bad
    $ ./getopts_test.sh --loglevel
    Parsing option: '--loglevel', value: ''
    $ ./getopts_test.sh --loglevel 11
    Parsing option: '--loglevel', value: '11'
    $ ./getopts_test.sh --loglevel=11
    Parsing option: '--loglevel', value: '11'
    

    Obviously getopts neither performs OPTERR checking nor option-argument parsing for the long options. The script fragment above shows how this may be done manually. The basic principle also works in the Debian Almquist shell ("dash"). Note the special case:

    getopts -- "-:"  ## without the option terminator "-- " bash complains about "-:"
    getopts "-:"     ## this works in the Debian Almquist shell ("dash")
    

    Note that, as GreyCat from over at http://mywiki.wooledge.org/BashFAQ points out, this trick exploits a non-standard behaviour of the shell which permits the option-argument (i.e. the filename in "-f filename") to be concatenated to the option (as in "-ffilename"). The POSIX standard says there must be a space between them, which in the case of "-- longoption" would terminate the option-parsing and turn all longoptions into non-option arguments.

提交回复
热议问题