2012-02-14 6 views
10

Todo lo que veo usa getopt o el ligeramente más lujoso getopts que solo admite opciones de un carácter (por ejemplo, -h pero no --help). Quiero hacer opciones largas y elegantes.¿Cómo puedo analizar argumentos largos en shell?

+1

posible duplicado de [Uso de getopts en script bash shell para obtener opciones de línea de comandos largas y cortas] (http://stackoverflow.com/questions/402377/using-getopts-in-bash-shell-script-to-get -long-and-short-command-line-options) –

+1

@JonathanLeffler Realmente no es un duplicado como 'getops' no siempre tiene que ser la respuesta – Potherca

+1

@Potherca: Y de hecho,' getopts' es * no * la respuesta, ya que explicado tanto en esta pregunta como en las respuestas a esa pregunta. – ruakh

Respuesta

14

que he hecho algo como this:

_setArgs(){ 
    while [ "${1:-}" != "" ]; do 
    case "$1" in 
     "-c" | "--configFile") 
     shift 
     configFile=$1 
     ;; 
     "-f" | "--forceUpdate") 
     forceUpdate=true 
     ;; 
     "-r" | "--forceRetry") 
     forceRetry=true 
     ;; 
    esac 
    shift 
    done 
} 

Como se puede ver, este es compatible tanto con el solo carácter y las opciones más largos agradable. Permite asociar valores con cada argumento, como en el caso de --configFile. También es bastante extensible, sin limitaciones artificiales en cuanto a qué opciones se pueden configurar, etc.

Como se incluyó anteriormente, la "${1:-}" evita un error "Variable no unido" cuando se ejecuta en modo fiesta "estricta" (set -euo pipefail).

+0

Esto funcionaría, pero no obedecería algunas convenciones: plegar argumentos de una sola letra, y cosas como '-configFile = filename' (the' = '). –

+1

@IanBicking - Muy cierto. Sin embargo, para mi caso, decidí permitir esto sobre la frustración con getopt/getops reflejado en las muchas (aunque aún valiosas) respuestas provistas en el duplicado marcado en http://stackoverflow.com/questions/402377/using-getopts -in-bash-shell-script-to-get-long-and-short-command-line-options. – ziesemer

+0

Ah ... esa pregunta no estaba entre los candidatos para duplicados cuando escribí mi pregunta. ¡Gracias! –

6

Suponiendo que "desea hacer opciones largas y elegantes" independientemente de la herramienta, simplemente vaya con getopt (getopts parece que se usa principalmente cuando la portabilidad es crucial). He aquí un example de la complejidad máxima que obtendrá:

params="$(getopt -o e:hv -l exclude:,help,verbose --name "$(basename "$0")" -- "[email protected]")" 

if [ $? -ne 0 ] 
then 
    usage 
fi 

eval set -- "$params" 
unset params 

while true 
do 
    case $1 in 
     -e|--exclude) 
      excludes+=("$2") 
      shift 2 
      ;; 
     -h|--help) 
      usage 
      ;; 
     -v|--verbose) 
      verbose='--verbose' 
      shift 
      ;; 
     --) 
      shift 
      break 
      ;; 
     *) 
      usage 
      ;; 
    esac 
done 

Con este código, puede especificar -e/--exclude más de una vez, y ${excludes[@]} contendrá todos los excluye dadas. Después del procesamiento (-- siempre está presente), todo lo que queda se almacena en [email protected].

+0

'basename' no toma la ruta como una opción, sino como un argumento. (No pude editar la respuesta, porque el sistema requiere al menos 6 ediciones de caracteres.) – jarno

+0

Gracias @jarno, no sé cómo se metió. – l0b0

+1

Por otro lado, creo que no es necesario que use '$ { 2-} ', pero' $ 2' es suficiente, ya que 'getopt' saldrá con un código distinto de cero, si no hubiera argumento para' -e', ¿no? – jarno

Cuestiones relacionadas