И так, мы хотим разбирать параметры командной строки в нашем скрипте, и мы хотим учесть
- Опции без аргументов
- Опции с аргументами
- Проверку отсутствия аргумента
- Проверку неизвестных опций
- Проверку отсутствия параметров
- Оформить эту часть скрипта как функцию
И вот вам сразу самый тру способ, к которому я смог прийти
#!/bin/bash
function check_arg(){
if [[ $2 == -* ]]; then
echo "Option $1 requires an argument" >&2
exit 1
fi
}
function parse_param()
{
if [ -z "$1" ];then
echo "Empty list of options" >&2
exit 1
fi
while getopts ":np:" opt; do
case $opt in
p)
check_arg "-p" "$OPTARG"
echo "-p(param) was triggered, Parameter: '$OPTARG'"
;;
n)
echo "-n(no param) was triggered"
;;
?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
:)
echo "Option -$OPTARG requires an argument (getopts)" >&2
exit 1
;;
esac
done
}
parse_param "$@"
И вот пример его использования
[bash]$ ./test.sh
Empty list of option
[bash]$ ./test.sh -m
Invalid option: -m
[bash]$ ./test.sh -n
-n(no param) was triggered
[bash]$ ./test.sh -n -p
-n(no param) was triggered
Option -p requires an argument (getopts)
[bash]$ ./test.sh -p -n
Option -p requires an argument
[bash]$ ./test.sh -p"1 2 3"
-p(param) was triggered, Parameter: '1 2 3'
Зачем я все это написал? Ведь наверно это в интернетах все уже давно расписано. Сейчас объясню. Пока я шел к этой простой реализации, я множество раз вставал на грабли использования getopts в том контексте в котором мне нужно. Поэтому я хотел бы ниже описать те грабли на которые я вставал по ходу, и которые привели меня, надеюсь, что на верный путь использования getopts.
Getopts в функции
Ошибки могут заключатся в том как вы передаете аргументы в эту функцию, вот например два неправильных способа
parse_param $1 $2 $3
parse_param "$1" "$2" "$3"
В первом случае, если в сам скрипт вы передавали аргумент так
[bash]$ ./test.sh -p"1 2 3"
То до функции parse_param они дойдут как parse_param –p 1 2 3, что, поверьте мне, не то чего вы ожидали.
Оковычивание аргументов помогает, но порождаю другую проблему. Теперь перестанет работать вот эта часть
:)
echo "Option -$OPTARG requires an argument (getopts)" >&2
exit 1
;;
В место этого $OPTARG будет пустой строкой, что вполне валидно с точки зрения getopts.
Так что делайте просто и корректно вот так
parse_param "$@"
Опции с аргументами и проверка аргумента
Для включения начальной защиты от отсутствия аргумента, каждую такую опцию необходимо завершать знаком «:» и добавить соответствующий обработчик
:)
echo "Option -$OPTARG requires an argument (getopts)" >&2
exit 1
;;
Зачем вот эта приблуда?
function check_arg(){
if [[ $2 == -* ]]; then
echo "Option $1 requires an argument" >&2
exit 1
fi
}
Попробуйте убрать вызов этой функции вот тут
check_arg "-p" "$OPTARG"
И сделайте вот такой вызов
[bash]$ ./test.sh -p -n
И вы получите что “-n” станет аргументом опции –p. Это то, чего вы ожидали? А я нет.
Не валидные аргументы
Для того что бы вот этот кусок кода делал то что вы хотите
?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
Список параметров getopts должен начинаться с «:» (getopts ":np:")
Надеюсь получилось не слишком эмоционально, и кому то это позволит сохранить время на более интересные занятие.
Автор: Cupper