¿Usar 'case $1 in' para leer las opciones de comando: varios indicadores después del guión y manejar indicadores inusuales?

¿Usar 'case $1 in' para leer las opciones de comando: varios indicadores después del guión y manejar indicadores inusuales?

Estoy creando un script bash que utiliza opciones largas y banderas cortas. Como quiero opciones largas, no puedo usar getopts. Intenté usar el siguiente código:

while test -n "$1"; do
  case "$1" in
        -o|--override)  NO_CHANGE=yes;shift 1;;
        -r|--reset)     OV_RESET=yes;shift 1;;
        -h|--help)      hthemehelp;shift 1;;
        *)              break;;
  esac
done

Esto funciona cuando lo invoco como myscr -o -ro myscr -h, pero cuando lo intento, myscr -orel programa simplemente ejecuta su comportamiento normal y al ejecutarlo myscr -or -hsale del ciclo antes de llegar a -h. Reemplazar breakpor continuecausas justas myscr -ory myscr -or -hcolgar.

Respuesta1

Pruébate esto para ver el tamaño:

#!/bin/bash
pleasereset=1
while test -n "$1"; do
   pleaseshift=0
   [[ pleasereset -eq 1 ]] && thisvar=$1 && pleasereset=0;
   case "$thisvar" in
      -o*|--override) echo "override!"; pleaseshift=1;;
      -r*|--reset) echo "reset!"; pleaseshift=1;;
      -h*|--help) echo "help!"; pleaseshift=1;;
      *) break ;;
   esac
   if [[ "$pleaseshift" = "1" ]];
   then
      testvar=${thisvar##-}
      if [[ ${#testvar} -gt 1 ]] && [[ ! ${thisvar} = --* ]];
      then
         thisvar=-$( echo "$testvar" | cut -c 2- )
      else
         shift 1; pleasereset=1;
      fi
   fi
done

Tenga en cuenta que en el primer parámetro que no coincida con ningún caso específico, el análisis del parámetro se detendrá, por lo que a ./foobar.sh -o --help -s -rno procesará el archivo -r. Esto se puede ajustar cambiando la *) break;;línea a manejo de errores, pero recuerde poner el pleaseshift=1!

Respuesta2

Quizás sea suficiente agregar la línea que desees:

while test -n "$1"; do
  case "$1" in
        -or|-ro)        OV_RESET=yes;NO_CHANGE=yes;shift 1;;
        -o|--override)  NO_CHANGE=yes;shift 1;;
        -r|--reset)     OV_RESET=yes;shift 1;;
        -h|--help)      hthemehelp;shift 1;;
        *)              break;;
  esac
done

o, más complejo, puedes poner el casebloque en una función con el shift 1fuera de ese bloque pero aún dentro del while.
Para elduplicadoopciones ( -or,, -ohque no son una de las largas, puede llamar recursivamente a la misma función para cada letra de case *)... Necesita una bandera si acaba de procesar $1como una opción larga. Sin embargo, en este caso expone su script tp mal comportamiento debido a errores tipográficos (por ejemplo, si escribo -overrider I will process-o -v -e -r -d`...)

información relacionada