И так, мы хотим разбирать параметры командной строки в нашем скрипте, и мы хотим учесть
И вот вам сразу самый тру способ, к которому я смог прийти
И вот пример его использования
Зачем я все это написал? Ведь наверно это в интернетах все уже давно расписано. Сейчас объясню. Пока я шел к этой простой реализации, я множество раз вставал на грабли использования getopts в том контексте в котором мне нужно. Поэтому я хотел бы ниже описать те грабли на которые я вставал по ходу, и которые привели меня, надеюсь, что на верный путь использования getopts.
Ошибки могут заключатся в том как вы передаете аргументы в эту функцию, вот например два неправильных способа
В первом случае, если в сам скрипт вы передавали аргумент так
То до функции parse_param они дойдут как parse_param –p 1 2 3, что, поверьте мне, не то чего вы ожидали.
Оковычивание аргументов помогает, но порождаю другую проблему. Теперь перестанет работать вот эта часть
В место этого $OPTARG будет пустой строкой, что вполне валидно с точки зрения getopts.
Так что делайте просто и корректно вот так
Для включения начальной защиты от отсутствия аргумента, каждую такую опцию необходимо завершать знаком «:» и добавить соответствующий обработчик
Зачем вот эта приблуда?
Попробуйте убрать вызов этой функции вот тут
И сделайте вот такой вызов
И вы получите что “-n” станет аргументом опции –p. Это то, чего вы ожидали? А я нет.
Для того что бы вот этот кусок кода делал то что вы хотите
Список параметров getopts должен начинаться с «:» (getopts ":np:")
Надеюсь получилось не слишком эмоционально, и кому то это позволит сохранить время на более интересные занятие.
- Опции без аргументов
- Опции с аргументами
- Проверку отсутствия аргумента
- Проверку неизвестных опций
- Проверку отсутствия параметров
- Оформить эту часть скрипта как функцию
И вот вам сразу самый тру способ, к которому я смог прийти
#!/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:")
Надеюсь получилось не слишком эмоционально, и кому то это позволит сохранить время на более интересные занятие.
