¿Cómo manejo los conmutadores en un script de shell?

¿Hay algunas herramientas integradas que reconozcan -x y --xxxx como conmutadores, y no como argumentos, o ¿tiene que revisar todas las variables de entrada, probar los guiones y luego analizar los argumentos a partir de entonces?

Respuesta

Utilice getopts .

Es bastante portátil como lo es 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, patrón de uso típico para getopts (utilizando informes de errores 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 

Comentarios

  • Debe mencionarse que getopt siempre debe verificarse como GNU getopt antes de usarlo, pero no debe ' usarlo de todos modos ya que getopts es más portátil (y generalmente más agradable) de todos modos. Si necesita llamarlo por alguna razón, llámelo de una manera específica de GNU, y asegúrese de que GETOPT_COMPATIBLE no esté en el entorno.
  • ¿Qué hacen los dos puntos en while getopts "ab:" opt?
  • @ user394 La : después de una letra de opción lo indica requiere un argumento. Un : como primer carácter significa suprimir los mensajes de error.

Responder

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[@]}" "$@" 

Comentarios

  • +1 por usar += con una matriz. No ' sabía que podía hacer eso. ¡Bien!

Respuesta

Tienes que escribir un ciclo para analizar los parámetros. De hecho, puedes usar getopts para hacerlo fácilmente.

Este es un ejemplo simple de la página de manual getopts:

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" "$*" 

Respuesta

Recientemente escribí un script para el trabajo que era versátil y permitía múltiples tipos de interruptores en cualquier orden. No puedo divulgar 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 … puedes ponerlo en n una subrutina y llámelo al final de su script:

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. Empecé a reescribirlo en Perl, que es mucho más adecuado para la tarea. Tenga esto en cuenta mientras trabaja en sus scripts en bash. Bash es ideal para scripts pequeños y oneliners, pero cualquier cosa más compleja y es mejor escribirla en Perl.

Tenga en cuenta que no he probado lo anterior, por lo que probablemente no funcione, pero obtienes una idea general.

Comentarios

  • La forma en que llamas options al final no es correcto, devolverá -bash: syntax error near unexpected token $@. Llámelo como options "$@".
  • Sí, confundí Perl y Bash. Corregida.
  • Esa condición while no debería ser (($#)) en su lugar.
  • ¿Por qué ¿Necesitarías dos conjuntos de paréntesis para $#? Editar: tienes ' tienes razón. Se corrigió en while (( "$#" ))

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *