Помощь при печати getopts когда нет cmd. Строковый аргумент был согласован - PullRequest
4 голосов
/ 21 марта 2012

Я пытаюсь использовать getopts в bash для анализа аргументов командной строки, но я не мог понять, как реализовать действие «по умолчанию», если не найдено ни одного аргумента (или не указан аргумент cmdline).

Это просто упрощенная версия того, что я пробовал до сих пор:

while getopts v:t:r:s:c: name;
do
        case $name in
        v) VALIDATE=1;;
        t) TEST=1;;
        r) REPORT=1;;
        s) SYNC=1;;
        c) CLEAR=1;;
        *) print_help; exit 2;;
        \?) print_help; exit 2;;
        esac
done

Есть ли какой-нибудь (простой) способ заставить его вызвать print_help; выход 2; на несоответствующий вход?

Ответы [ 4 ]

4 голосов
/ 21 марта 2012

Просматривая ваш вопрос и комментарии к ответу Адитьи, я бы порекомендовал следующее:

[getopts]$ cat go
#!/bin/bash

function print_help { echo "Usage" >&2 ; } 

while getopts vtrsc name; do
    case $name in
        v) VALIDATE=1;;
        t) TEST=1;;
        r) REPORT=1;;
        s) SYNC=1;;
        c) CLEAR=1;;
        ?) print_help; exit 2;;
    esac
done

echo "OPTIND: $OPTIND"
echo ${#@}

shift $((OPTIND - 1))

while (( "$#" )); do
    if [[ $1 == -* ]] ; then
        echo "All opts up front, please." >&2 ; print_help ; exit 2
    fi
    echo $1
    shift
done

Поскольку каждый из этих параметров имеет логический флаг, вам не нужно (и на самом делене хочу) аргументы, поэтому мы избавляемся от двоеточий.Ни один из этих символов не находится в IFS, поэтому нам не нужно заключать его в кавычки, так или иначе, это будет один токен для getopts.

Далее, мы меняем \? на один ? иизбавьтесь от *, поскольку * будет соответствовать перед литералом \?, и мы могли бы также объединить правила в одно совпадение по умолчанию.Это хорошо, поскольку любой параметр, указанный с префиксом -, должен быть параметром, и пользователи будут ожидать сбоя программы, если они укажут параметр, который вы не ожидаете.

getoptsпроанализируйте первое, что не является аргументом, и установите OPTIND в значение этой позиции.В этом случае мы будем сдвигать OPTIND - 1 (так как опции индексируются 0) спереди.Затем мы пройдемся по этим аргументам, сместив их, повторив их или потерпев неудачу, если они начинаются с -.

И для проверки:

[getopts]$ ./go
OPTIND: 1
0
[getopts]$ ./go -t -v go go
OPTIND: 3
4
go
go
[getopts]$ ./go -d -v go go
./go: illegal option -- d
Usage
[getopts]$ ./go -t go -v go -d
OPTIND: 2
5
go
All opts up front, please.
Usage
3 голосов
/ 04 декабря 2015

Попробуйте следующий обходной путь:

# Parse the arguments.
while getopts ':h?f:' opts; do
  case ${opts} in

    f) # Foo argument.
      ;;

    # My other arguments.

    \? | h | *) # Prints help.
      grep " .)\ #" $0
      exit 0
      ;;
  esac
done

Таким образом, в основном -? / -h напечатает параметры с комментариями на основе своего собственного источника.Указание : перед параметрами выводит справку и для любого другого неизвестного аргумента.

2 голосов
/ 21 марта 2012

v:t:r:s:c: должно быть в двойных кавычках

 "v:t:r:s:c:"

Судя по опубликованному вами сценарию, возможно, вам не нужны все эти двоеточия :

Также вам не нужно *)

1 голос
/ 21 марта 2012

Вам нужно указать начальное двоеточие в строке опции getopts, если вы хотите включить ? для соответствия недопустимой опции - :vtrsc. Также вам не нужна обратная косая черта до ?

...