Bash getopts: распознавание отрицательных вариантов (-x- или +x)?

(Аналогично этому, но в bash.)

У меня есть существующий сценарий bash, который использует встроенную функцию getopts для распознавания -s (только флаг - без аргумента). Я обнаружил, что использую этот параметр каждый раз, поэтому я хотел бы сделать его по умолчанию, если -s- или +s не указано в командной строке. Однако, хотя ksh getopts может обрабатывать +s, я не могу найти эту возможность в руководстве по bash getopts.

Мои текущие обходные пути:

  1. использовать s:, чтобы я мог распознать -s- по $OPTARG="-"; или
  2. чтобы заменить -s другим вариантом, например, -d (для "нельзя").

Однако проблема #1 состоит в том, что он проглатывает следующий аргумент, если я случайно укажу -s, а проблема #2 состоит в том, что он использует другую букву переключения, отличную от той, которая уже есть в моей мышечной памяти. Я надеюсь, что может быть простой способ разобрать -s- или +s в bash.

  • util-linux getopt(1) также не отображается иметь +s. Он может обрабатывать необязательные аргументы, поэтому может принимать -s-. Тем не менее, я не использовал getopt(1) раньше, поэтому был бы признателен за подсказки о том, как не выстрелить себе в ногу.
  • BashFAQ 035 говорит: "Проанализируйте сами". если у вас уже есть написанная подпрограмма, которая выполняет +s или -s-, я бы хотел ее увидеть.

Мой текущий цикл разбора аргументов очень прост:

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

person cxw    schedule 24.10.2016    source источник


Ответы (1)


Последовательность отрицательных флагов (+abcdef +g) отличается от обычной последовательности (-abcdef -g) только знаком плюс. Таким образом, вы можете просто вернуть значение флага для префикса +.

Вторая форма отрицательной последовательности столь же проста. Просто удалите последний символ (-) и отмените нормальное значение флага.

Пример

Следующий скрипт принимает все упомянутые форматы, например. -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'
person Ruslan Osmanov    schedule 25.10.2016