Захват недопустимых параметров getopt
Я использую getopt
(не getops
), чтобы предоставить возможность моему скрипту bash обрабатывать параметры и переключатели (как длинные --option, так и короткие-o формы).
Я хотел бы иметь возможность ловить недопустимые параметры и обрабатывать их, как правило, повторяя, что пользователь должен попробовать cmd --help
и затем выход из сценария.
дело в том, что недопустимые параметры пойманы getopt, который сам выводит сообщение, такое как " getopt: недопустимый параметр -- 'x'"
вот шаблон, который я использую для установки параметров getopt:
set -- $(getopt -o $SHORT_OPTIONS -l $LONG_OPTIONS -- "$@")
где оба $LONG_OPTIONS и $SHORT_OPTIONS являются разделенным запятыми списком опций.
вот как я обрабатываю обработку параметров:
while [ $# -gt 0 ]
do
case "" in
-h|--help)
cat <<END_HELP_OUTPUT
Help
----
Usage: ./cmd.sh
END_HELP_OUTPUT
shift;
exit
;;
--opt1)
FLAG1=true
shift
;;
--opt2)
FLAG2=true
shift
;;
--)
shift
break
;;
*)
echo "Option is not a valid option."
echo "Try './cmd.sh --help for more information."
shift
exit
;;
esac
done
getopt -q
будет подавлять вывод, но моя схема захвата в case
заявление по-прежнему не делает то, что я ожидаю. Вместо этого программа просто выполняется, несмотря на недопустимые аргументы.
6 ответов
этой вид стиля работает для меня:
params="$(getopt -o d:h -l diff:,help --name "$cmdname" -- "$@")"
if [ $? -ne 0 ]
then
usage
fi
eval set -- "$params"
unset params
while true
do
case in
-d|--diff)
diff_exec=(${2-})
shift 2
;;
-h|--help)
usage
exit
;;
--)
shift
break
;;
*)
usage
;;
esac
done
Это не самое надежное решение, но это разумно; он полагается на следующее:
- сообщение об ошибке, что
getopt
печать имеет префикс " getopt:" - предполагается, что приемлемо пройти через очищенную версию
getopt
сообщение об ошибке, дополненное пользовательской информацией.
фрагмент кода:
# Invoke getopt; suppress its stderr initially.
args=$(getopt -o $SHORT_OPTIONS -l $LONG_OPTIONS -- "$@" 2>/dev/null)
if [[ $? -ne 0 ]]; then # getopt reported failure
# Rerun the same getopt command so we can capture stderr output *only* this time.
# Inefficient (and a potential maintenance headache, if literals were involved), but this will only execute in case of invalid input.
# Alternatively, redirect the first getopt invocation's stderr output to a temp. file and read it here.
errmsg=$(getopt -o $SHORT_OPTIONS -l $LONG_OPTIONS -- "$@" 2>&1 1>&-)
# Strip getopt's prefix and augment with custom information.
echo -e "${errmsg#getopt: }\nTry './cmd.sh --help for more information." 1>&2
exit 1
fi
вам вообще нужно использовать getopt? Если вы просто используете
while [ $# -gt 0 ]; do
case "" in
-d|--diff)
diff_exec=(${2-})
shift
;;
-h|--help)
usage
exit
;;
--)
break
;;
*)
usage
;;
esac
shift
done
тогда вы собственный код делает проверку.
Я обнаружил, что это работает как последний элемент в заявлении getopts case:
*) eval echo " Unrecognized arg \$$[OPTIND-1]"; Использование; выход ;;
Я не уверен, что это может помочь, но getopt (1) использует getopt (3) и если я правильно помню getopt (3) подавить сообщение об ошибке, если первый символ OPTSTRING двоеточие.
вот синтаксический анализ командной строки, который я использовал. Он может быть улучшен парсинг логика обработки отсутствующих параметров.
для командной строки: - A AA-b BB-CC, результат s/b a=AA b=BB c=CC
OPT=( "$@" ) # Parses the command line into words.
for [[ I=0;I<${#OPT[@]};I++ ]]
do
case "${OPT[$I]}" in
-a) a=${OPT[$I+1]} ;;
-b) b=${OPT[$I+1]} ;;
-c) c=${OPT[$I+1]} ;;
esac
done