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))
Estou tentando isso dentro de uma função, mas quando tento executar a função, recebo este erro "basename: opção inválida - 'b'". Parece que está tentando passar o "-bash" para basenameo traço principal.
Morgan Estes
5
imside uma função "$FUNCNAME"não use "$0". Além disso, addlocal OPTIND OPTARG
glenn jackman
Obrigado. FUNCNAMEtrabalho. Eu tenho todas as minhas funções em um único arquivo, então isso é perfeito para estendê-las para algo útil para outras pessoas.
Morgan Estes
5
@sigur, certifique-se de citar "$usage"todos os lugares em que você o usa.
Glenn Jackman
1
Para que serve shift $((OPTIND - 1))?
hpaknia
45
O primeiro argumento para um script de shell está disponível como variável $1, portanto, a implementação mais simples seria
Sim, embora o OP não tenha especificado bash e [seja a versão compatível com POSIX.
seb
Nota - Para uso interno function: você deve substituir exit 0por returnse não quiser finalizar seu shell após executar sua função. (Eu já fiz isso antes 😂) #
Illuminator
29
aqui está uma parte que eu uso para iniciar um servidor 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
É um pouco estranho que eu coloquei o start stop restart em um caso separado, mas deve funcionar
se você der uma opção vazia para -d; não será loop infinito?
Zerobane
Por que você sai 1 na função auxiliar?
jeantimex
17
Para uma solução rápida de opção única, use if
Se você tiver apenas uma única opção para verificar e sempre será a primeira opção ( $1), a solução mais simples será a ifcom um teste ( [). Por exemplo:
Observe que a compatibilidade com o posix =também funcionará ==.
Por que citar $1?
A razão pela qual as $1aspas precisam ser colocadas entre aspas é que, se não houver $1, o shell tentará executar if [ == "-h" ]e falhar, porque ==recebeu apenas um argumento quando esperava dois:
$ [=="-h"]
bash:[:==: unary operator expected
Para algo mais complexo, use getoptougetopts
Conforme sugerido por outros , se você tiver mais do que uma única opção simples ou precisar da sua opção para aceitar um argumento, você definitivamente deve procurar a complexidade extra do uso getopts.
Você também pode considerar o getoptprograma em vez do shell interno getopts. Permite o uso de opções longas e opções após argumentos não opcionais (por exemplo, foo a b c --verboseao invés de apenas foo -v a b c). Esta resposta do Stackoverflow explica como usar o GNU getopt.
Obrigado! Estou usando felizmente getopts há um ano, mas também darei uma olhada no getopt.
Ttpppp 01/03
1
Infelizmente, o link para o Tutorial de 60 segundos getopts está morto; parece que bashcurescancer.com não existe mais. Aqui está um link para a versão do Wayback Machine .
Respostas:
Aqui está um exemplo para o bash:
Para usar isso dentro de uma função:
"$FUNCNAME"
vez de$(basename "$0")
local OPTIND OPTARG
antes de ligargetopts
fonte
basename
o traço principal."$FUNCNAME"
não use"$0"
. Além disso, addlocal OPTIND OPTARG
FUNCNAME
trabalho. Eu tenho todas as minhas funções em um único arquivo, então isso é perfeito para estendê-las para algo útil para outras pessoas."$usage"
todos os lugares em que você o usa.shift $((OPTIND - 1))
?O primeiro argumento para um script de shell está disponível como variável
$1
, portanto, a implementação mais simples seriaMas o que anubhava disse.
fonte
[
seja a versão compatível com POSIX.function
: você deve substituirexit 0
porreturn
se não quiser finalizar seu shell após executar sua função. (Eu já fiz isso antes 😂) #aqui está uma parte que eu uso para iniciar um servidor VNC
É um pouco estranho que eu coloquei o start stop restart em um caso separado, mas deve funcionar
fonte
Para uma solução rápida de opção única, use
if
Se você tiver apenas uma única opção para verificar e sempre será a primeira opção (
$1
), a solução mais simples será aif
com um teste ([
). Por exemplo:Observe que a compatibilidade com o posix
=
também funcionará==
.Por que citar
$1
?A razão pela qual as
$1
aspas precisam ser colocadas entre aspas é que, se não houver$1
, o shell tentará executarif [ == "-h" ]
e falhar, porque==
recebeu apenas um argumento quando esperava dois:Para algo mais complexo, use
getopt
ougetopts
Conforme sugerido por outros , se você tiver mais do que uma única opção simples ou precisar da sua opção para aceitar um argumento, você definitivamente deve procurar a complexidade extra do uso
getopts
.Como referência rápida, eu gosto do tutorial Getopts de 60 segundos . †
Você também pode considerar o
getopt
programa em vez do shell internogetopts
. Permite o uso de opções longas e opções após argumentos não opcionais (por exemplo,foo a b c --verbose
ao invés de apenasfoo -v a b c
). Esta resposta do Stackoverflow explica como usar o GNUgetopt
.† jeffbyrnes mencionou que o link original morreu, mas felizmente o caminho de volta foi arquivado pela máquina .
fonte
Melhor usar o recurso getopt do bash. Consulte estas perguntas e respostas para obter mais ajuda: Usando getopts no script shell do bash para obter opções de linha de comando longas e curtas
fonte
Eu acho que você pode usar caso para isso ...
fonte