Ответы:
Использование getopts
.
Это довольно переносимо, как в спецификации POSIX. К сожалению, он не поддерживает длинные варианты.
Смотрите также этот getopts
учебник, предоставленный вики bash-hackers, и этот вопрос от stackoverflow.
Если вам нужны только короткие варианты, типичный шаблон использования getopts
(с использованием не-тихой отчетности об ошибках):
# process arguments "$1", "$2", ... (i.e. "$@")
while getopts "ab:" opt; do
case $opt in
a) aflag=true ;; # Handle -a
b) barg=$OPTARG ;; # Handle -b argument
\?) ;; # Handle error: unknown option or missing required argument.
esac
done
while getopts "ab:" opt
?
:
после опции указывает, что она требует аргумента. A :
в качестве первого символа означает подавление сообщений об ошибках.
Я предполагаю, что вы используете Bash или подобное. Пример:
all=false
long=false
while getopts ":hal" option; do
case $option in
h) echo "usage: $0 [-h] [-a] [-l] file ..."; exit ;;
a) all=true ;;
l) long=true ;;
?) echo "error: option -$OPTARG is not implemented"; exit ;;
esac
done
# remove the options from the positional parameters
shift $(( OPTIND - 1 ))
ls_opts=()
$all && ls_opts+=( -a )
$long && ls_opts+=( -l )
# now, do it
ls "${ls_opts[@]}" "$@"
+=
с массивом. Не знал, что ты мог сделать это. Ницца!
Вы должны написать цикл для разбора параметров. На самом деле вы можете использовать getopts
команду, чтобы сделать это легко.
Это простой пример со getopts
страницы руководства:
aflag=
bflag=
while getopts ab: name
do
case $name in
a) aflag=1;;
b) bflag=1
bval="$OPTARG";;
?) printf "Usage: %s: [-a] [-b value] args\n" $0
exit 2;;
esac
done
if [ ! -z "$aflag" ]; then
printf "Option -a specified\n"
fi
if [ ! -z "$bflag" ]; then
printf 'Option -b "%s" specified\n' "$bval"
fi
shift $(($OPTIND - 1))
printf "Remaining arguments are: %s\n" "$*"
Недавно я написал сценарий для работы, которая была бы универсальной и позволяла использовать разные типы переключателей в любом порядке. Я не могу раскрыть полный сценарий по очевидным юридическим причинам (не говоря уже о том, что у меня его сейчас нет), но вот суть этого ... вы можете поместить его в подпрограмму и вызвать в конце вашего сценария:
options () {
if [ -n "$1" ]; then # test if any arguments passed - $1 will always exist
while (( "$#" )); do # process ALL arguments
if [ "$1" = ^-t$ ]; then # -t short for "test"
# do something here THEN shift the argument
# shift removes it from $@ and reduces $# by
# one if you supply no argument
shift
# we can also process multiple arguments at once
elif [[ "$1" =~ ^--test=[:alnum:]{1,8}$ ]] && [[ "$2" =~ ^-t2$ ]] && [[ -n "$3" ]]; then # check for 3 arguments
# do something more then remove them ALL from the arg list
shift 3
else
echo "No matching arguments!"
echo "Usage: [script options list here]"
fi
done
else
echo "Usage: [script options list here]"
exit 0
fi
}
options "$@" # run options and loop through/process ALL arguments
Я рекомендую ограничить ваш bash скрипт до 400 строк / 15k символов; Мой вышеупомянутый сценарий вырос до этого размера и стало очень трудно работать. Я начал переписывать его на Perl, который гораздо лучше подходит для этой задачи. Имейте это в виду, работая над своими скриптами в bash. Bash отлично подходит для небольших сценариев и подписчиков, но для чего-то более сложного, и вам лучше написать его на Perl.
Обратите внимание, я не проверял вышеизложенное, поэтому, вероятно, это не сработало, но вы получили общее представление об этом.
options
в конце, неверно, оно вернется -bash: syntax error near unexpected token $@
. Назовите это как options "$@"
.
while
условие не должно быть (($#))
вместо этого?
$#
? Редактировать: вы правы. Исправлено этоwhile (( "$#" ))
getopt
перед использованием его всегда следует проверять как GNU getopt, но вы все равно не должны его использовать, так как в любом случаеgetopts
он более переносим (и, как правило, лучше). Если вы делаете потребность назвать его по какой - то причине, называют его в GNU-определенным образом, и убедитесь , чтоGETOPT_COMPATIBLE
это не в окружающей среде.