Я не думаю, что есть стандартный метод (т.е. помимо реализации всего этого с нуля), который будет доступен, не говоря уже о том, чтобы в одиночку были широко доступны в оболочках.
Хотя КШ
поддерживает довольно мощный встроенный
. Исходя из этого (и на ваши вполне сложные требования) я изложил возможное решение решение на основе KSH
с следующим фрагментом кода:
while getopts ":[-][[n]:][99:verbose][s]" opt
do case $opt in
(n) n_arg=$OPTARG ;;
(99) verbose=1 ;;
(s) s=1 ;;
(*) arg_rest+=( "${@:OPTIND-1:1}" ) ;;
esac
done
shift OPTIND-1
printf "main opt(%s)=%s\n" "-n" "$n_arg"
printf "main opt(%s)=%s\n" "--verbose" "$verbose"
printf "main opt(%s)=%s\n" "-s" "$s"
function delegate
{
while getopts ":[-][i][98:long]" opt
do case $opt in
(i) int=1 ;;
(98) long=1 ;;
esac
done
shift OPTIND-1
printf "func opt(%s)=%s\n" "-i" "$int"
printf "func opt(%s)=%s\n" "--long" "$long"
}
printf "Delegate: '%s'\n" "${arg_rest[@]}"
delegate "${arg_rest[@]}"
Программа сначала анализирует все параметры, устанавливает внутренние переменные по мере необходимости и хранит Неизвестные варианты в массиве. Затем вы видите несколько printf
для управления настройками. Затем определение функции, где остальные варианты должны быть делегированы; Функция может быть заменена командой. Наконец звонок функции (или соответствует некоторой другой команде) с остальными аргументами.
(для описания ksh
ГУМКЦ
Функции
Функции вызов из сеанса KSH
Getopts - Motortopts
.)
Запуск этой программы производит этот вывод:
$ ksh ./getopts_script -s -n 23 --verbose -i --long
main opt(-n)=23
main opt(--verbose)=1
main opt(-s)=1
Delegate: '-i'
Delegate: '--long'
func opt(-i)=1
func opt(--long)=1
для внедрения оболочки функции Getopts, которая поддерживает длинные варианты, см. https://github.com/stephane-chazelas/misc-scripts/blob/master/getopts_long. Sh
Заманчиво попробовать getopt
заказать заранее известные опции. К сожалению, он отвергает все неизвестные аргументы и немедленно прекращает парсинг.
Но пока опции не слишком сложны, можно обмануть бэшовых getopt
. Некоторое вдохновение было взято из mkaurball
. Под источником следуют пещеры.
#!/bin/bash
while [ $OPTIND -le $# ]
do
if getopts ":sn:-:" argument
then
case $argument in
s) echo "-$argument" ;;
n) echo "-$argument with argument $OPTARG" ;;
\?) pass+=("-$OPTARG") ;;
-) lastarg=$((OPTIND - 1))
case "${!lastarg}" in
--verbose) echo "--verbose" ;;
--*) pass+=("--$OPTARG") ;;
*) echo "invalid argument: -"
exit 1 ;;
esac ;;
:) echo "$OPTARG without argument"
exit 1 ;;
esac
else
pass+=("${!OPTIND}")
let OPTIND++
fi
done
echo pass: "${pass[@]}"
getopts
не используется в качестве условия для , в то время как
, что привело бы к остановке цикла, как только бы он не столкнулся с каким-либо позиционным параметром, то есть с чем угодно, что не является ни опцией, ни аргументом к ней. Вместо этого эти случаи добавляются в массив, собирающий параметры для pass
on. :-
, что заставляет getopts
рассматривать длинные опции -длинные
в качестве короткой опции -
с аргументом -длинные
. Использование без осторожности, смешивание тире в середине короткой опции (как -s-n
) может нарушить это, поэтому лучше проверить, действительно ли фактический параметр начинается с двух тире. Таким образом, подход будет неудачным, если обернутая программа хочет видеть опции типа -short-with-dashes
в качестве опции. -etopts
, двойные тире также проглатываются. Этого можно хотеть, но этого также можно избежать, вставив ["${!OPTIND}" != '--' ] &&
перед getopts
случае
.