Ну совсем маленькая заметка по getopts

в 8:36, , рубрики: bash, linux, scripts, Песочница, метки: , ,

И так, мы хотим разбирать параметры командной строки в нашем скрипте, и мы хотим учесть

  • Опции без аргументов
  • Опции с аргументами
  • Проверку отсутствия аргумента
  • Проверку неизвестных опций
  • Проверку отсутствия параметров
  • Оформить эту часть скрипта как функцию

И вот вам сразу самый тру способ, к которому я смог прийти

#!/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

Источник

Поделиться

* - обязательные к заполнению поля