Bash getopts: recognition of negative options (-x- or + x)?

(Similar to this , but in bash.)

I have an existing bash script that uses built-in getopts for recognition -s(only a flag - no argument). I find that I use this parameter every time, so I want to make it the default if -s-or is not specified on the command line +s. However, although ksh getoptscan handle it+s , I cannot find this feature in the bash getoptsmanual .

My current workarounds:

  • use s:so that I can recognize -s-on $OPTARG= "-"; or
  • replace -swith another option, for example -d(for "do not").

However, in # 1 there is a problem that it swallows the next argument if I accidentally indicates -s, and # 2 has a problem with the fact that it uses a different shift letter than the one I already have in my muscle memory. I hope there may be an easy way to parse -s-or +sin bash.

  • util-linux getopt (1) also does not +s. It can handle optional arguments, so it can accept -s-. However, I have not used it getopt(1)before, so I would like pointers on how not to shoot in the leg.
  • BashFAQ 035 says, "figure it out for yourself." if you have already written a program that does +sor -s-, I would really like to see it.

My current arg parsing loop is very simple:

while getopts "nthps" opt ; do
    case "$opt" in
        <other cases cut>
        (s)     saw_s="yes"
                ;;
    esac
done
shift $((OPTIND-1))
+4
1

(+abcdef +g) (-abcdef -g) . +.

. (-) .

script , . -ns -n -s -n- -ns- +ns +n +s.

arglist='ns'

while (( $# )); do
  arg="$1"

  # Parse -abcdef- (negative form of -abcdef) options
  if [ "${arg:0:1}" = '-' -a "${arg#${arg%?}}" = '-' ]; then
    flag_val=no
    arg="${arg%?}" # -abcdef- becomes -abcdef
  elif [ "${arg:0:1}" = '+' ]; then
    flag_val=no
    arg="${arg/#+/-}"
  else
    flag_val=yes
  fi

  # OPTIND is the index of the next argument to be processed.
  # We are going to parse "$arg" from the beginning, so we need
  # to reset it to 1 before calling getopts.
  OPTIND=1

  while getopts "$arglist" opt "$arg"; do
    case "$opt" in
      s) saw_s="$flag_val" ;;
      n) saw_n="$flag_val" ;;
    esac
  done

  shift
done

# Set default values
: ${saw_s:=yes}
: ${saw_n:=no}

printf "saw_s='%s'\nsaw_n='%s'\n" "$saw_s" "$saw_n"

$ ./pargs.sh
saw_s='yes'
saw_n='no'
$ ./pargs.sh -s
saw_s='yes'
saw_n='no'
$ ./pargs.sh +s
saw_s='no'
saw_n='no'
$ ./pargs.sh -s-
saw_s='no'
saw_n='no'
$ ./pargs.sh -s- +s -s
saw_s='yes'
saw_n='no'
$ ./pargs.sh -s +s
saw_s='no'
saw_n='no'
$ ./pargs.sh +s -s
saw_s='yes'
saw_n='no'
$ ./pargs.sh -s -s-
saw_s='no'
saw_n='no'
$ ./pargs.sh -sn
saw_s='yes'
saw_n='yes'
$ ./pargs.sh -sn -s-
saw_s='no'
saw_n='yes'
$ ./pargs.sh -sn +s
saw_s='no'
saw_n='yes'
$ ./pargs.sh +sn
saw_s='no'
saw_n='no'
$ ./pargs.sh -sn-
saw_s='no'
saw_n='no'
$ ./pargs.sh -sn- -n
saw_s='no'
saw_n='yes'
+2

Source: https://habr.com/ru/post/1658707/


All Articles