Using getopts inside a Bash function

后端 未结 3 804
臣服心动
臣服心动 2020-11-28 04:59

I\'d like to use getopts inside a function that I have defined in my .bash_profile. The idea is I\'d like to pass in some flags to this function to alter its be

相关标签:
3条回答
  • 2020-11-28 05:20

    Here is simple example of getopts usage within shell function:

    #!/usr/bin/env bash
    t() {
      local OPTIND
      getopts "a:" OPTION
      echo Input: $*, OPTION: $OPTION, OPTARG: $OPTARG
    }
    t "$@"
    t -a foo
    

    Output:

    $ ./test.sh -a bc
    Input: -a bc, OPTION: a, OPTARG: bc
    Input: -a foo, OPTION: a, OPTARG: foo
    

    As @Adrian pointed out, local OPTIND (or OPTIND=1) needs to be set as shell does not reset OPTIND automatically between multiple calls to getopts (man bash).

    The base-syntax for getopts is:

    getopts OPTSTRING VARNAME [ARGS...]
    

    and by default, not specifying arguments is equivalent to explicitly calling it with "$@" which is: getopts "a:" opts "$@".

    In case of problems, these are the used variables for getopts to check:

    • OPTIND - the index to the next argument to be processed,
    • OPTARG - variable is set to any argument for an option found by getopts,
    • OPTERR (not POSIX) - set to 0 or 1 to indicate if Bash should display error messages generated by the getopts.

    Further more, see: Small getopts tutorial at The Bash Hackers Wiki

    0 讨论(0)
  • 2020-11-28 05:22

    As @Ansgar points out, the argument to your option is stored in ${OPTARG}, but this is not the only thing to watch out for when using getopts inside a function. You also need to make sure that ${OPTIND} is local to the function by either unsetting it or declaring it local, otherwise you will encounter unexpected behaviour when invoking the function multiple times.

    t.sh:

    #!/bin/bash
    
    foo()
    {
        foo_usage() { echo "foo: [-a <arg>]" 1>&2; exit; }
    
        local OPTIND o a
        while getopts ":a:" o; do
            case "${o}" in
                a)
                    a="${OPTARG}"
                    ;;
                *)
                    foo_usage
                    ;;
            esac
        done
        shift $((OPTIND-1))
    
        echo "a: [${a}], non-option arguments: $*"
    }
    
    foo
    foo -a bc bar quux
    foo -x
    

    Example run:

    $ ./t.sh
    a: [], non-option arguments:
    a: [bc], non-option arguments: bar quux
    foo: [-a <arg>]
    

    If you comment out # local OPTIND, this is what you get instead:

    $ ./t.sh
    a: [], non-option arguments:
    a: [bc], non-option arguments: bar quux
    a: [bc], non-option arguments:
    

    Other than that, its usage is the same as when used outside of a function.

    0 讨论(0)
  • 2020-11-28 05:26

    The argument is stored in the varable $OPTARG.

    function t() {
      echo $*
      getopts "a:" OPTION
      echo $OPTION
      echo $OPTARG
    }
    

    Output:

    $ t -a bc
    -a bc
    a
    bc
    0 讨论(0)
提交回复
热议问题