Sep 182012
 

Oggi stavo scrivendo uno script bash che doveva gestire alcuni argomenti di input, e così ho studiato getopt, questo è un modo comodo ed elegante per gestire i parametri di input in uno script bash. Con esso è possibile definire switch (presenti o no) o parametri con un’opzione, in modo da rendere il vostro semplice script bash molto più professionale.

Vediamo come usare questo comando e le relative opzioni.

Si prega di notare che su Linux ci sono due modi diversi per analizzare gli argomenti della riga di comando. Vi è una utility chiamata getopt (man 1 getopt). Questa utility è disponibile in tutte le shell. Poi in bash, c’è un altro strumento integrato per l’analisi degli argomenti chiamata getopts (è un comando built-in, quindi non ha la propria man-page – Provate help getopts). In questo articolo vi parlerò della prima opzione, dopo alcuni problemi con script che non funzionavano più in dash preferisco usare programmi esterni di piccole dimensioni piuttosto che comandi incorporati nella bash.

In Debian e Ubuntu il comando getopt è contenuto nel pacchetto util-linux, che viene automaticamente installato, mi aspetto che anche su altre distribuzioni Linux lo si trovi senza bisogno di installare pacchetti aggiuntivi.

Uso base



In getopt i parametri vengono analizzati da sinistra a destra. Ogni parametro è classificato come opzione breve, opzione lunga, un argomento ad una opzione, o un parametro non-opzione.

 Una semplice opzione breve è un `- ‘ seguito da un carattere di opzione breve. Se l’opzione ha un argomento obbligatorio, può essere scritto subito dopo il carattere di opzione o come parametro successivo (cioè separato da spazio bianco sulla riga di comando). Se l’opzione ha un argomento facoltativo, esso deve essere scritto direttamente dopo il carattere opzione se presente.

E’ possibile specificare diverse opzioni brevi dopo un ‘-‘ , fino a quando tutti (tranne forse l’ultimo) non hanno argomenti richiesti o opzionali.

Una opzione lunga normalmente inizia con `– ‘ seguita dal nome dell’opzione lunga. Se l’opzione ha un argomento obbligatorio, può essere scritto direttamente dopo il nome dell’opzione lunga, separati da `= ‘, o come l’argomento successivo (es. separati da spazio bianco sulla riga di comando). Se l’opzione ha un argomento facoltativo, deve essere scritto direttamente dopo il nome dell’opzione lunga, separato da `= ‘, se presente. Le opzioni lunghe possono essere abbreviate, purché l’abbreviazione non sia ambigua.

A mio parere il modo migliore per presentare questo comando è con un esempio.
Voglio uno script che possa gestire le opzioni brevi: -h -1 -2 e -3 con un argomento, come -3=Ciao, e che possa anche gestire le seguenti opzioni lunghe –help, –uno, –due e –tre con un argomento.

#!/bin/bash
 
# Execute getopt on the arguments passed to this program, identified by the special character $@
PARSED_OPTIONS=$(getopt -n "$0"  -o h123: --long "help,one,two,three:"  -- "$@")
 
#Bad arguments, something has gone wrong with the getopt command.
if [ $? -ne 0 ];
then
  exit 1
fi
 
# A little magic, necessary when using getopt.
eval set -- "$PARSED_OPTIONS"
 
 
# Now goes through all the options with a case and using shift to analyse 1 argument at a time.
#$1 identifies the first argument, and when we use shift we discard the first argument, so $2 becomes $1 and goes again through the case.
while true;
do
  case "$1" in
 
    -h|--help)
      echo "usage $0 -h -1 -2 -3 or $0 --help --one --two --three"
     shift;;
 
    -1|--one)
      echo "One"
      shift;;
 
    -2|--two)
      echo "Dos"
      shift;;
 
    -3|--three)
      echo "Tre"
 
      # We need to take the option of the argument "three"
      if [ -n "$2" ];
      then
        echo "Argument: $2"
      fi
      shift 2;;
 
    --)
      shift
      break;;
  esac
done


Le opzioni che abbiamo usato con getopt in questo esempio sono:

-l, –longoptions (longopts)
               Le opzioni lunghe (più caratteri) che possono essere riconosciute. Più di un nome di opzione può essere specificato in una sola volta, separando i nomi con una virgola. Questa opzione può essere dato più di una volta, i longopts sono cumulativi. Ogni nome di opzione lunga presente in longopts può essere seguita da un due punti (:) per indicare che ha un argomento obbligatorio, e da due due punti (::) per indicare che ha un argomento facoltativo.

-o, –options (shortopts)
               Le opzioni brevi (di un carattere) che possono essere riconosciute. Se questa opzione non viene trovata, il primo parametro di getopt che non inizia con un `- ‘(e non è un argomento opzionale) è usato come stringa breve opzioni. Ogni carattere di opzione breve può essere seguito da un due punti (:) per indicare che ha un argomento obbligatorio, e da due due punti (::) per indicare che ha un argomento facoltativo.

Conclusioni

Se si guarda l’esempio si può vedere che è più lungo descrivere come funziona getopt che utilizzarlo, è sufficiente definire l’elenco delle opzioni brevi e lunghe e gestirle con un ciclo while e un case, e avrete uno script bash che può elegantemente gestire le opzioni.

Popular Posts:

Flattr this!

  3 Responses to “Analizzare le opzioni di uno script bash con getopt”

  1. Thank you for the useful tip.

    A minor correction:
    ‘-h|–help’ should be ‘-h|–help)’

  2. I’ve been writing bash scripts for years, and I’ve never heard of getopt (or getopts) before. getopt seems very simple to use, and as you said, makes the script accept input parameters just like any other professional program would, which is awesome. Thanks for sharing – your article is very easy to follow, and your example is awesome – I’m adding this to my Linux notes folder that I always reference.

    BTW, you’re missing a ‘)’ after ‘-h|–help’.
    Also, while your script works perfectly on Debian (and many other distributions I’m sure), OS X doesn’t seem to like it 🙂

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

(required)

(required)

*