2010-04-15 22 views
18

Hay una serie de preguntas sobre este tipo de cosas, pero imaginemos que estamos apuntando a un sistema Linux genérico con getopt y getopts instalados (no es que usemos ninguno, pero parecen populares)Análisis del argumento del script de Shell

¿Cómo analizo dos largos | argruments (--example-opción sencilla --example) y cortas (-e | -esimple-ejemplo | -e simple ejemplo)

Respuesta

33

desea utilizar getopt con larga y opciones cortas Un ejemplo de código de trabajo:

# Parse arguments 
TEMP=$(getopt -n $PROGRAM_NAME -o p:P:cCkhnvVS \ 
--long domain-password:,pop3-password:\   
,create,cron,kill,help,no-sync-passwords,version,verbose,skip-pop3 \ 
-- "[email protected]")                

# Die if they fat finger arguments, this program will be run as root 
[ $? = 0 ] || die "Error parsing arguments. Try $PROGRAM_NAME --help"  

eval set -- "$TEMP" 
while true; do  
     case $1 in 
       -c|--create) 
         MODE="CREATE"; shift; continue 
       ;;          
       -C|--cron)        
         MODE="CRON"; shift; continue 
       ;;          
       -k|--kill)        
         MODE="KILL"; shift; continue 
       ;;          
       -h|--help)        
         usage       
         exit 0       
       ;;          
       -n|--no-sync-passwords)    
         SYNC_VHOST=0; shift; continue 
       ;;          
       -p|--domain-password)     
         DOMAIN_PASS="$2"; shift; shift; continue 
       ;;            
       -P|--pop3-password)        
         POP3_PASS="$2"; shift; shift; continue 
       ;;            
       -v|--version)         
         printf "%s, version %s\n" "$PROGRAM_NAME" "$PROGRAM_VERSION" 
         exit 0              
       ;;                 
       -v|--verbose)              
         VERBOSE=1; shift; continue         
       ;;                 
       -S|--skip-pop3)              
         SKIP_POP=1; shift; continue         
       ;;                 
       --)                 
         # no more arguments to parse         
         break              
       ;;                 
       *)                 
         printf "Unknown option %s\n" "$1"       
         exit 1              
       ;;                 
     esac                   
done  

Nota, die es una función que se ha definido previamente (no mostrado).

La opción -n le dice a getopt que informe errores como el nombre de mi programa, no como getopt. -o define una lista de opciones cortas (: después de que una opción indique un argumento necesario) y --long especifica la lista de opciones largas (correspondiente a las opciones cortas).

El resto es simplemente un interruptor, llamando al shift de manera apropiada para avanzar el puntero del argumento. Tenga en cuenta que llamar al shift; shift; es solo un hábito difícil. En el mundo actualmente moderno, probablemente sea suficiente con shift 2.

El moderno getopt es bastante consistente en las plataformas más nuevas, sin embargo, es posible que encuentre algunos problemas de portabilidad en sistemas más antiguos (circa pre Redhat 9). Consulte man getopt para obtener información acerca de la compatibilidad con versiones anteriores. Sin embargo, es poco probable que se encuentre con la necesidad de hacerlo.

Finalmente, después de analizar las opciones, puede volver a llamar:

eval set -- "[email protected]" 

Esto moverá el puntero argumento para cualquier otra cosa a la izquierda en la línea de comandos después de getopt se hizo opciones de análisis. A continuación, puede simplemente shift para seguir leyéndolos. Por ejemplo, si un comando se veía así:

./foo --option bar file1.txt file2.txt file3.txt 

No se olvide de hacer una opción útil -h/--help para imprimir sus nuevas opciones de lujo, una vez que haya terminado. :) Si haces que la salida help2man sea amigable, tienes una página man instantánea para usar con tu nueva herramienta.

Editar

En la mayoría de las distribuciones, usted puede encontrar más getopt ejemplo de código en /usr/share/doc/util-linux/examples, que debería haber sido instalado por defecto.

+0

Me doy cuenta de que no estoy haciendo cordura aquí para comprobar si hay varios comandos que configuran MODE. En este caso, era aceptable que la última opción simplemente tomara precedencia, y el pegado solo tenía la intención de ser informativo sobre una forma de usar 'getopt'. –

+0

Me han recomendado utilizar 'getopt()' varias veces. Llámame estúpido, pero no puedo entender cómo funciona. Como mi script necesitaba un equivalente de Windows, utilicé esto (http://stackoverflow.com/a/3981086/314056). En mi opinión, ese es un enfoque mucho más limpio y menos mágico. ¿Puedo hacer algo similar en Linux? – Christian

+0

@Christian Podría hacer algo similar con BASH, '% 1' se convierte en' $ 1' (y '$ 2' respectivamente si' $ 1' espera un argumento). De hecho, muchas personas simplemente lo hacen de esa manera, siguen cíclicamente a través de los argumentos a través de 'shift' y ejecutan el argumento actual a través de un interruptor.'getopt' simplemente se encarga de toda esta magia, además de la verificación obligatoria de los argumentos para usted, a muchos les gusta esa conveniencia. –

Cuestiones relacionadas