Optional option argument with getopts

前端 未结 11 1315
while getopts \"hd:R:\" arg; do
  case $arg in
    h)
      echo \"usgae\" 
      ;;
    d)
      dir=$OPTARG
      ;;
    R)
      if [[ $OPTARG =~ ^[0-9]+$ ]];then         


        
11条回答
  •  半阙折子戏
    2020-11-28 08:57

    Inspired in @calandoa's answer (the only one that actually works!), I've made a simple function that can make it easy to be used multiple times.

    getopts_get_optional_argument() {
      eval next_token=\${$OPTIND}
      if [[ -n $next_token && $next_token != -* ]]; then
        OPTIND=$((OPTIND + 1))
        OPTARG=$next_token
      else
        OPTARG=""
      fi
    }
    

    An example usage:

    while getopts "hdR" option; do
      case $option in
      d)
        getopts_get_optional_argument $@
        dir=${OPTARG}
        ;;
      R)
        getopts_get_optional_argument $@
        level=${OPTARG:-1}
        ;;
      h)
        show_usage && exit 0
        ;;
      \?)
        show_usage && exit 1
        ;;
      esac
    done
    

    This gives us a practical way to get "that missing feature" in getopts :)

    NOTE that nevertheless command-line options with optional args seems to be discouraged explicitly

    Guideline 7: Option-arguments should not be optional.

    but I have no intuitive way to implement my case without this: I have 2 modes that are activated by either using one flag or other, and those have both an argument with a clear default. Introducing a third flag just to disambiguate makes it look a bad CLI style.

    I've tested this with many combinations, including all in @aaron-sua's answer and works well.

提交回复
热议问题