Просматривая ваш вопрос и комментарии к ответу Адитьи, я бы порекомендовал следующее:
[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