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))
Estoy intentando esto dentro de una función, pero cuando intento ejecutar la función me sale este error "basename: opción no válida - 'b'". Parece que está tratando de pasar "-bash" basenamecon el guión principal.
Morgan Estes
55
imponer una función de uso "$FUNCNAME"no "$0". Además, agreguelocal OPTIND OPTARG
glenn jackman el
Gracias. FUNCNAMEtrabajos. Tengo todas mis funciones dentro de un solo archivo, por lo que es perfecto para extenderlas en algo útil para otros.
Morgan Estes
55
@sigur, asegúrese de citar "$usage"cada lugar donde lo use.
Glenn Jackman
1
¿Para qué sirve shift $((OPTIND - 1))?
hpaknia
45
El primer argumento para un script de shell está disponible como la variable $1, por lo que la implementación más simple sería
Sí, aunque el OP no especificó bash, y [es la versión compatible con POSIX.
seb
Nota - Para usar dentro function: debe reemplazar exit 0con returnsi no desea terminar su shell después de ejecutar su función. (Lo he hecho antes 😂)
Illuminator
29
Aquí hay una parte que lo uso para iniciar un 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
shiftbreak;;-*)
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
Es un poco extraño que coloque el inicio, parada, reinicio en un caso separado, pero debería funcionar
Tenga en cuenta que para la compatibilidad posix =funcionará tan bien como ==.
¿Por qué cotizar $1?
La razón por la que $1debe incluirse entre comillas es que si no existe $1, el shell intentará ejecutarse if [ == "-h" ]y fallará porque ==solo se le ha dado un solo argumento cuando esperaba dos:
$ [=="-h"]
bash:[:==: unary operator expected
Para cualquier uso más complejo getoptogetopts
Según lo sugerido por otros , si tiene más de una opción simple, o necesita su opción para aceptar un argumento, entonces definitivamente debe optar por la complejidad adicional del uso getopts.
También puede considerar el getoptprograma en lugar del shell integrado getopts. Permite el uso de opciones largas y opciones después de argumentos sin opciones (por ejemplo, en foo a b c --verboselugar de solo foo -v a b c). Esta respuesta de Stackoverflow explica cómo usar GNU getopt.
¡Gracias! He estado felizmente usando getopts durante un año, pero también echaré un vistazo a getopt.
tttppp
1
Lamentablemente, el enlace al Tutorial de los 60 segundos getopts está muerto; parece que bashcurescancer.com ya no existe. Aquí hay un enlace a la versión de la máquina Wayback .
Respuestas:
Aquí hay un ejemplo para bash:
Para usar esto dentro de una función:
"$FUNCNAME"
lugar de$(basename "$0")
local OPTIND OPTARG
antes de llamargetopts
fuente
basename
con el guión principal."$FUNCNAME"
no"$0"
. Además, agreguelocal OPTIND OPTARG
FUNCNAME
trabajos. Tengo todas mis funciones dentro de un solo archivo, por lo que es perfecto para extenderlas en algo útil para otros."$usage"
cada lugar donde lo use.shift $((OPTIND - 1))
?El primer argumento para un script de shell está disponible como la variable
$1
, por lo que la implementación más simple seríaPero lo que dijo Anubhava.
fuente
[
es la versión compatible con POSIX.function
: debe reemplazarexit 0
conreturn
si no desea terminar su shell después de ejecutar su función. (Lo he hecho antes 😂)Aquí hay una parte que lo uso para iniciar un servidor VNC
Es un poco extraño que coloque el inicio, parada, reinicio en un caso separado, pero debería funcionar
fuente
Para una solución rápida de opción única, use
if
Si solo tiene una opción para verificar y siempre será la primera opción (
$1
), entonces la solución más simple esif
con una prueba ([
). Por ejemplo:Tenga en cuenta que para la compatibilidad posix
=
funcionará tan bien como==
.¿Por qué cotizar
$1
?La razón por la que
$1
debe incluirse entre comillas es que si no existe$1
, el shell intentará ejecutarseif [ == "-h" ]
y fallará porque==
solo se le ha dado un solo argumento cuando esperaba dos:Para cualquier uso más complejo
getopt
ogetopts
Según lo sugerido por otros , si tiene más de una opción simple, o necesita su opción para aceptar un argumento, entonces definitivamente debe optar por la complejidad adicional del uso
getopts
.Como referencia rápida, me gusta el tutorial de 60 segundos de getopts . †
También puede considerar el
getopt
programa en lugar del shell integradogetopts
. Permite el uso de opciones largas y opciones después de argumentos sin opciones (por ejemplo, enfoo a b c --verbose
lugar de solofoo -v a b c
). Esta respuesta de Stackoverflow explica cómo usar GNUgetopt
.† jeffbyrnes mencionó que el enlace original murió pero afortunadamente la forma en que la máquina lo había archivado.
fuente
Es mejor usar la instalación getopt de bash. Consulte estas preguntas y respuestas para obtener más ayuda: Uso de getopts en el script de shell bash para obtener opciones de línea de comando largas y cortas
fuente
Creo que puedes usar el caso para esto ...
fuente