usage="$(basename "$0") [-h] [-s n] -- program to calculate the answer to life, the universe and everything
where:
-h show this help text
-s set the seed value (default: 42)"
seed=42while getopts ':hs:' option;docase"$option"in
h) echo "$usage"
exit
;;
s) seed=$OPTARG
;;:) printf "missing argument for -%s\n""$OPTARG">&2
echo "$usage">&2
exit 1;;
\?) printf "illegal option: -%s\n""$OPTARG">&2
echo "$usage">&2
exit 1;;esacdone
shift $((OPTIND -1))
Я пытаюсь сделать это внутри функции, но когда я пытаюсь запустить функцию, я получаю сообщение об ошибке «basename: invalid option - 'b'». Похоже, он пытается передать "-bash" basenameс ведущим тире.
Морган Эстес,
5
внутри функции использовать "$FUNCNAME"нет "$0". Также добавлюlocal OPTIND OPTARG
Гленн Джекман
Спасибо. FUNCNAMEработает. У меня все функции находятся в одном файле, так что это идеально подходит для расширения их во что-то полезное для других.
Морган Эстес,
5
@sigur, не забудьте процитировать "$usage"каждое место, где вы его используете.
Гленн Джекман
1
Для чего shift $((OPTIND - 1))?
hpaknia
45
Первый аргумент сценария оболочки доступен как переменная $1, поэтому простейшей реализацией будет
Спасибо @MarkBooth, опечатка исправлена (плюс улучшение за счет
заключения
Вы должны иметь привычку заключать if в [[...]] для условных
выражений,
2
Да, хотя OP не указывал bash и [является версией, совместимой с POSIX.
сен
Примечание. Для использования внутри function: следует заменить exit 0на, returnесли вы не хотите завершать работу оболочки после запуска функции. (Я делал это раньше 😂)
Illuminator
29
вот часть, которую я использую для запуска сервера VNC
#!/bin/bash
start(){
echo "Starting vnc server with $resolution on Display $display"#your execute command here mine is below#vncserver :$display -geometry $resolution}
stop(){
echo "Killing vncserver on display $display"#vncserver -kill :$display}########################## The command line help ##########################
display_help(){
echo "Usage: $0 [option...] {start|stop|restart}">&2
echo
echo " -r, --resolution run with the given resolution WxH"
echo " -d, --display Set on which display to host on "
echo
# echo some stuff here for the -a or --add-options
exit 1}################################# Check if parameters options ## are given on the commandline #################################while:docase"$1"in-r |--resolution)if[ $# -ne 0 ]; then
resolution="$2"# You may want to check validity of $2fi
shift 2;;-h |--help)
display_help # Call your function
exit 0;;-d |--display)
display="$2"
shift 2;;-a |--add-options)# do something here call function# and write it in your help function display_help()
shift 2;;--)# End of all options
shift
break;;-*)
echo "Error: Unknown option: $1">&2## or call function display_help
exit 1;;*)# No more optionsbreak;;esacdone###################### # Check if parameter ## is set too execute #######################case"$1"in
start)
start # calling function start();;
stop)
stop # calling function stop();;
restart)
stop # calling function stop()
start # calling function start();;*)# echo "Usage: $0 {start|stop|restart}" >&2
display_help
exit 1;;esac
Немного странно, что я поместил старт-стоп-рестарт в отдельный случай, но он должен работать
если вы дадите пустую опцию -d; не будет бесконечного цикла?
zerobane
Почему вы выходите из 1 во вспомогательной функции?
jeantimex
17
Для быстрого решения с одним вариантом используйте if
Если у вас есть только один вариант для проверки, и он всегда будет первым вариантом ( $1), то самым простым решением является использование iftest ( [). Например:
Обратите внимание, что для совместимости с posix =будет работать так же, как ==.
Зачем цитировать $1?
Причина, по которой $1необходимо заключить в кавычки, заключается в том, что, если их нет, $1оболочка попытается запустить if [ == "-h" ]и потерпит неудачу, потому ==что был дан только один аргумент, когда он ожидал два:
$ [=="-h"]
bash:[:==: unary operator expected
Для более сложного использования getoptилиgetopts
Как предложено на других , если у вас есть более чем один вариант простой, или нужна ваша возможность принять аргумент, то вы должны обязательно пойти на дополнительную сложность использования getopts.
Вы также можете рассмотреть getoptпрограмму вместо встроенной оболочки getopts. Он позволяет использовать длинные параметры и параметры после аргументов без параметров (например, foo a b c --verboseа не просто foo -v a b c). Этот ответ Stackoverflow объясняет, как использовать GNU getopt.
Ответы:
вот пример для bash:
Чтобы использовать это внутри функции:
"$FUNCNAME"
вместо$(basename "$0")
local OPTIND OPTARG
перед звонкомgetopts
источник
basename
с ведущим тире."$FUNCNAME"
нет"$0"
. Также добавлюlocal OPTIND OPTARG
FUNCNAME
работает. У меня все функции находятся в одном файле, так что это идеально подходит для расширения их во что-то полезное для других."$usage"
каждое место, где вы его используете.shift $((OPTIND - 1))
?Первый аргумент сценария оболочки доступен как переменная
$1
, поэтому простейшей реализацией будетНо что сказал анубхава.
источник
[
является версией, совместимой с POSIX.function
: следует заменитьexit 0
на,return
если вы не хотите завершать работу оболочки после запуска функции. (Я делал это раньше 😂)вот часть, которую я использую для запуска сервера VNC
Немного странно, что я поместил старт-стоп-рестарт в отдельный случай, но он должен работать
источник
Для быстрого решения с одним вариантом используйте
if
Если у вас есть только один вариант для проверки, и он всегда будет первым вариантом (
$1
), то самым простым решением является использованиеif
test ([
). Например:Обратите внимание, что для совместимости с posix
=
будет работать так же, как==
.Зачем цитировать
$1
?Причина, по которой
$1
необходимо заключить в кавычки, заключается в том, что, если их нет,$1
оболочка попытается запуститьif [ == "-h" ]
и потерпит неудачу, потому==
что был дан только один аргумент, когда он ожидал два:Для более сложного использования
getopt
илиgetopts
Как предложено на других , если у вас есть более чем один вариант простой, или нужна ваша возможность принять аргумент, то вы должны обязательно пойти на дополнительную сложность использования
getopts
.В качестве краткого справочника мне понравился 60-секундный учебник по getopts . †
Вы также можете рассмотреть
getopt
программу вместо встроенной оболочкиgetopts
. Он позволяет использовать длинные параметры и параметры после аргументов без параметров (например,foo a b c --verbose
а не простоfoo -v a b c
). Этот ответ Stackoverflow объясняет, как использовать GNUgetopt
.† Джеффбирнес упомянул, что исходная ссылка умерла, но, к счастью , машина на обратном пути ее заархивировала.
источник
Лучше использовать getopt в bash. Пожалуйста, посмотрите эти вопросы и ответы для получения дополнительной помощи: Использование getopts в сценарии оболочки bash для получения длинных и коротких параметров командной строки
источник
я думаю, вы можете использовать для этого случай ...
источник