bash getopts con opciones múltiples y obligatorias

¿Es posible usar getopts para procesar múltiples opciones juntas? Por ejemplo, myscript -iR o myscript -irv.

Además, tengo una situación en la que, según un script de condición, necesitaría una opción obligatoria. Por ejemplo, si el argumento del script es un directorio, tendré que especificar la opción -R o -r junto con cualquier otra opción (myscript -iR mydir o myscript -ir mydir o myscript -i -r mydir o myscript -i -R mydir), en el caso de archivo solo -i es suficiente (myscript -i myfile).

Intenté buscar pero no obtuve ninguna respuesta.

preguntado el 01 de julio de 12 a las 04:07

1 Respuestas

Puede concatenar las opciones que proporcione y getopts los separará. En tus case instrucción manejará cada opción individualmente.

Puede establecer una bandera cuando se ven las opciones y verificar para asegurarse de que las "opciones" obligatorias (!) estén presentes después de la getopts el bucle se ha completado.

Aquí hay un ejemplo:

#!/bin/bash
rflag=false
small_r=false
big_r=false

usage () { echo "How to use"; }

options=':ij:rRvh'
while getopts $options option
do
    case "$option" in
        i  ) i_func;;
        j  ) j_arg=$OPTARG;;
        r  ) rflag=true; small_r=true;;
        R  ) rflag=true; big_r=true;;
        v  ) v_func; other_func;;
        h  ) usage; exit;;
        \? ) echo "Unknown option: -$OPTARG" >&2; exit 1;;
        :  ) echo "Missing option argument for -$OPTARG" >&2; exit 1;;
        *  ) echo "Unimplemented option: -$OPTARG" >&2; exit 1;;
    esac
done

if ((OPTIND == 1))
then
    echo "No options specified"
fi

shift $((OPTIND - 1))

if (($# == 0))
then
    echo "No positional arguments specified"
fi

if ! $rflag && [[ -d $1 ]]
then
    echo "-r or -R must be included when a directory is specified" >&2
    exit 1
fi

Esto representa una implementación de referencia completa de un getopts función, pero es solo un boceto de un script más grande.

contestado el 31 de mayo de 19 a las 04:05

Muchas gracias Denis. He usado las banderas como sugeriste. Traté de simplificar la lógica concatenando opciones y almacenándolas en una variable y luego procesando según las opciones proporcionadas. - Ramesh Samane

La diferencia entre la opción no implementada y la desconocida es que para la primera se suministró una opción que coincide con un carácter de opción en $options, pero no hay entrada en el case declaración y para este último se suministró una opción que no coincide con ningún carácter en $options. - dennis williamson

Tenga en cuenta que no tiene que anteponer los nombres de las variables con $ dentro de bloques aritméticos; así que puedes hacer shift $((OPTIND-1)) - kbolino

Por cierto * ) echo "Unimplemented option: -$OPTARG" >&2; exit 1;; debería indicar -$option y no -$OPTARG de lo contrario dice el argumento a la opción no está implementada en lugar de la bandera está sin implementar. La forma original de usar -$OPTARG: ` ./foo.bash -m foo Opción no implementada: -foo ` Si usa -$option obtienes lo que se esperaba: ` ./foo -m foo Opción no implementada: -m ` - Hechicero élfico

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.