¿Hay algunas herramientas integradas que reconocerán -x
y --xxxx
como modificadores, y no argumentos, o tiene que revisar todas las variables de entrada, probar guiones y luego analizar los argumentos a partir de entonces?
¿Hay algunas herramientas integradas que reconocerán -x
y --xxxx
como modificadores, y no argumentos, o tiene que revisar todas las variables de entrada, probar guiones y luego analizar los argumentos a partir de entonces?
Respuestas:
Uso getopts
.
Es bastante portátil ya que está en la especificación POSIX. Lamentablemente no admite opciones largas.
Consulte también este getopts
tutorial, cortesía de la wiki de bash-hackers y esta pregunta de stackoverflow.
Si solo necesita opciones cortas, el patrón de uso típico para getopts
(utilizando informes de error no silenciosos) es:
# process arguments "$1", "$2", ... (i.e. "$@")
while getopts "ab:" opt; do
case $opt in
a) aflag=true ;; # Handle -a
b) barg=$OPTARG ;; # Handle -b argument
\?) ;; # Handle error: unknown option or missing required argument.
esac
done
while getopts "ab:" opt
hacer?
:
Después de una letra de opción significa que requiere un argumento. A :
como primer carácter significa suprimir los mensajes de error.
Supongo que estás usando bash o similar. Un ejemplo:
all=false
long=false
while getopts ":hal" option; do
case $option in
h) echo "usage: $0 [-h] [-a] [-l] file ..."; exit ;;
a) all=true ;;
l) long=true ;;
?) echo "error: option -$OPTARG is not implemented"; exit ;;
esac
done
# remove the options from the positional parameters
shift $(( OPTIND - 1 ))
ls_opts=()
$all && ls_opts+=( -a )
$long && ls_opts+=( -l )
# now, do it
ls "${ls_opts[@]}" "$@"
+=
con una matriz. No sabía que podías hacer eso. ¡Agradable!
Tienes que escribir un ciclo para analizar los parámetros. De hecho, puede usar el getopts
comando para hacerlo fácilmente.
Este es un ejemplo simple de getopts
la página del manual:
aflag=
bflag=
while getopts ab: name
do
case $name in
a) aflag=1;;
b) bflag=1
bval="$OPTARG";;
?) printf "Usage: %s: [-a] [-b value] args\n" $0
exit 2;;
esac
done
if [ ! -z "$aflag" ]; then
printf "Option -a specified\n"
fi
if [ ! -z "$bflag" ]; then
printf 'Option -b "%s" specified\n' "$bval"
fi
shift $(($OPTIND - 1))
printf "Remaining arguments are: %s\n" "$*"
Recientemente escribí un script para el trabajo que era versátil y permitía múltiples tipos de interruptores en cualquier orden. No puedo revelar el guión completo por razones legales obvias (sin mencionar que no lo tengo conmigo en este momento), pero aquí está el meollo del asunto ... puede ponerlo en una subrutina y llamarlo al final de tu guión:
options () {
if [ -n "$1" ]; then # test if any arguments passed - $1 will always exist
while (( "$#" )); do # process ALL arguments
if [ "$1" = ^-t$ ]; then # -t short for "test"
# do something here THEN shift the argument
# shift removes it from $@ and reduces $# by
# one if you supply no argument
shift
# we can also process multiple arguments at once
elif [[ "$1" =~ ^--test=[:alnum:]{1,8}$ ]] && [[ "$2" =~ ^-t2$ ]] && [[ -n "$3" ]]; then # check for 3 arguments
# do something more then remove them ALL from the arg list
shift 3
else
echo "No matching arguments!"
echo "Usage: [script options list here]"
fi
done
else
echo "Usage: [script options list here]"
exit 0
fi
}
options "$@" # run options and loop through/process ALL arguments
Recomiendo limitar su script bash a menos de 400 líneas / 15k caracteres; mi guión antes mencionado creció más allá de este tamaño y se volvió muy difícil trabajar en él. Comencé a reescribirlo en Perl, que es mucho más adecuado para la tarea. Tenga eso en cuenta mientras trabaja en sus scripts en bash. Bash es ideal para pequeños scripts y líneas, pero cualquier cosa más compleja y es mejor escribirlo en Perl.
Tenga en cuenta que no he probado lo anterior, por lo que probablemente no funcione, pero se entiende la idea general.
options
al final no es correcta, volverá -bash: syntax error near unexpected token $@
. Llámalo como options "$@"
.
while
condición no debería ser (($#))
en su lugar?
$#
? Editar: tienes razón. Lo arregló awhile (( "$#" ))
getopt
siempre debe verificarse como GNU getopt antes de usarlo, pero no debe usarlo de todos modos ya quegetopts
es más portátil (y generalmente más agradable) de todos modos. Si haces necesidad de llamar por alguna razón, lo llaman de una manera específica de GNU, y asegurarse de queGETOPT_COMPATIBLE
no se encuentra en el medio ambiente.