Dimensione: 21963
Commento:
|
Dimensione: 22199
Commento:
|
Le cancellazioni sono segnalate in questo modo. | Le aggiunte sono segnalate in questo modo. |
Linea 50: | Linea 50: |
La stringa '''optsting''' elenca le opzioni nel formato corto che il comando può incontrare durante il parsing. Questa stringa può essere racchiusa tra doppi apici. Al suo interno i nomi delle opzioni possono essere elencati senza separatori. Se il carattere che indica l'opzione è seguito dai due punti, l'opzione prevede un parametro obbligatorio; se è seguito da una coppia di doppi punti, il parametro è opzionale. '''parameters''' è la stringa degli argomenti su cui operare. Generalmente si indica come '''parameters''' la stringa dei parametri posizionali passati allo script, cioè "$@"; se si vuole passare una stringa alternativa, questa non va racchiusa tra apici, né singoli né doppi. | La stringa '''optsting''' elenca le opzioni nel formato corto che il comando può incontrare durante il parsing. Questa stringa può essere racchiusa tra doppi apici. Al suo interno i nomi delle opzioni possono essere elencati senza separatori. Se il carattere che indica l'opzione è seguito dai due punti, l'opzione prevede un parametro obbligatorio; se è seguito da una coppia di doppi punti, il parametro è opzionale. '''parameters''' è la stringa degli argomenti su cui operare. Generalmente si pone uguale alla stringa dei parametri posizionali passati allo script, cioè "$@". Se si vuole passare una stringa alternativa, questa non va racchiusa tra apici, né singoli né doppi. |
Linea 86: | Linea 86: |
}}} Ora, ''getopt'' accetta anche le opzioni nella versione lunga 'file', con un parametro obbligatorio, e 'dir' con un parametro facoltativo. | }}} Ora, ''getopt'' accetta anche le opzioni nella versione lunga: 'help' senza parametro, 'file' con un parametro obbligatorio e 'dir' con un parametro facoltativo. |
Linea 89: | Linea 89: |
}}} Qui ''getopt'' accetta le stesse opzioni del caso precedente, ma queste possono esse indicate anche nello ''stile XF86''. | }}} Qui ''getopt'' accetta le stesse opzioni del caso precedente, ma queste possono essere indicate anche nello ''stile XF86''. |
Linea 98: | Linea 98: |
* ''getopt'' riconosce qualsiasi abbreviazione non ambigua delle opzioni nel formato lungo: '--fi' sarà quindi riconosciuta come ''--file'' nel caso non ci sia rischio di ambiguità con altre opzioni. | * ''getopt'' riconosce qualsiasi abbreviazione non ambigua delle opzioni nel formato lungo. Facendo riferimento agli esempi precedenti, l'opzione '--fi' sarà quindi riconosciuta come ''--file'' nel caso non ci sia rischio di ambiguità con altre opzioni. |
Linea 101: | Linea 101: |
Lo script che segue accetta l'opzione 'a' senza parametro, l'opzione 'b' con parametro obbligatorio e l'opzione 'c' con parametro facoltativo. Sono accettate anche le rispettive varianti lunghe 'a-lunga', 'b-lunga' e 'c-lunga'. | Lo script che segue accetta l'opzione 'a' senza parametro, l'opzione 'b' con parametro obbligatorio e l'opzione 'c' con parametro facoltativo. Sono accettate anche le rispettive varianti lunghe 'a-lunga', 'b-lunga' e 'c-lunga' nello ''stile Gnu' (con due trattini come prefisso). |
Linea 218: | Linea 218: |
* Il comando '''shift''' viene utilizzato all'interno del costrutto ''case'' per avanzare nella lettura dei parametri posizionali passati allo script. Nel caso di un'opzione senza parametro o dei due trattini '--', si ''shifta'' di una posizione | * Il comando '''shift''' viene utilizzato all'interno del costrutto ''case'' per avanzare nella lettura dei parametri posizionali passati allo script. Nel caso di un'opzione senza parametro, si ''shifta'' di una posizione; nel caso dei due trattini '--' si ''shifta'' di una posizione e si interrompe il parsing; nel caso di una opzione con parametro facoltativo, si ''shifta'' di due posizioni. |
Linea 224: | Linea 224: |
* A differenza di ''getopt'', il comando ''getopts'' è un built-in della shell. Questo comporta che: | * Il comando ''getopts'' è un built-in della shell. Questo comporta che: |
Problemi in questa pagina? Segnalali in questa discussione
Introduzione
Prima di vedere nel dettaglio gli strumenti che le varie shell disponibili su Ubuntu forniscono per fare il parsing della riga di comando, è utile fare una breve introduzione per capire alcuni concetti fondamentali.
Facendo riferimento al comando tar, un modo generico per lanciare questo comando nel terminale è dato da:
tar -cv -f mioArchivio.tar directoryDaArchiviare
Il comando è composto da una serie di stringhe dette argomenti. Il primo argomento è il nome stesso del comando, mentre i successivi sono indicati con il nome di parametri posizionali.
Questi ultimi possono essere suddivisi in alcune categorie logiche:
una opzione è un argomento, generalmente incluso nella documentazione del comando, la cui presenza modifica il comportamento del comando stesso.
Una opzione può esistere nella versione corta, che consiste in un trattino seguito da una singola lettera (ad esempio, '-f' nel comando precedente), o nella versione lunga. Di quest'ultima, si hanno due formati: nello stile GNU si ha un doppio trattino seguito da una serie di due o più lettere (ad esempio '--help'); lo stile XF86 ha un singolo trattino come prefisso (ad esempio '-verbose').
Più opzioni corte possono essere raggruppate in un singolo argomento (ad esempio, '-cv' nel comando precedente).un parametro è un argomento che può fornire informazioni aggiuntive al comando o a un'opzione a cui si riferisce. Nel comando precedente, 'mioArchivio.tar' è un parametro dell'opzione '-f', mentre 'directoryDaArchiviare' è un parametro per il comando 'tar'. Qualora si volesse aggiungere al comando un parametro che ha l'aspetto di una opzione, ma non la sua funzione, è possibile separarlo dal resto del comando scrivendolo dopo un doppio trattino '--'
Fatta questa premessa, è utile notare che il comando precedente è equivalente al comando:
tar -vcf mioArchivio.tar directoryDaArchiviare
In questo comando, tutte le opzioni corte sono state riunite e ne è stato cambiato l'ordine. Analogamente, l'ordine con cui vengono scritte le opzioni lunghe, insieme ai loro eventuali parametri, non ne altera il significato.
Il parsing della riga di comando è quindi la procedura con cui un comando, o uno script, interpretano le istruzioni fornite dall'utente tramite una opportuna combinazione di opzioni e parametri. Nel caso di uno script, per poter effettuare facilmente questo parsing, si possono usare due strumenti molto versatili: getopt e getopts (fare attenzione alla 's' finale nel secondo comando).
getopt
getopt analizza una stringa di parametri e ne restituisce una versione canonica, ossia una versione standardizzata che potrà poi essere analizzata più facilmente. Generalmente, questa analisi successiva viene eseguita in un ciclo while, all'interno del quale si esegue un'analisi delle casistiche possibili tramite costrutto case.
Pro
Supporta sia le opzioni corte, sia quelle lunghe. Di quest'ultime, supporta sia lo stile GNU, sia lo stile XF86.
- È in grado di gestire opzioni con parametri che siano obbligatori o facoltativi.
Contro
La versione descritta in questa guida non è un built-in della shell, ma è inclusa nel pacchetto util-linux e precedentemente nella glibc (cioè, la GNU lib c). Ciononostante, può essere facilmente installata nelle distribuzioni in cui non sia presente di default. È disponibile anche per Inoltre, il comando
getopt --test
restituisce un exit code uguale a 4, se la versione installata è quella descritta in questa guida, e può quindi essere usato per un test preliminare all'interno dello script.
Funzionamento
Il comando getopt può essere chiamato con tre diverse sintassi. La più semplice è:
getopt optstring parameters
La stringa optsting elenca le opzioni nel formato corto che il comando può incontrare durante il parsing. Questa stringa può essere racchiusa tra doppi apici. Al suo interno i nomi delle opzioni possono essere elencati senza separatori. Se il carattere che indica l'opzione è seguito dai due punti, l'opzione prevede un parametro obbligatorio; se è seguito da una coppia di doppi punti, il parametro è opzionale. parameters è la stringa degli argomenti su cui operare. Generalmente si pone uguale alla stringa dei parametri posizionali passati allo script, cioè "$@". Se si vuole passare una stringa alternativa, questa non va racchiusa tra apici, né singoli né doppi.
Le altre due sintassi hanno rispettivamente la forma
getopt [options] [--] optstring parameters
e
getopt [options] -o|--options optstring [options] [--] parameters
optstring e parameters sono gli stessi visti nella prima sintassi, mentre le parti racchiuse tra le parentesi quadre sono opzionali e la barra verticale indica che l'opzione alla sua sinistra e quella alla sua destra sono equivalenti.
La stringa options, che nella seconda sintassi può essere presente in due punti, contiene una serie di opzioni e rispettivi parametri che modificano il funzionamento del comando. Tra queste, le più importanti sono:
-l|--long|--longoptions longopts
L'opzione '-l', o le equivalenti '--long' e '--longoptions', indicano che durante il parsing si potranno incontrare opzioni lunghe, i cui nomi vengono specificati nella stringa longopts. Questa stringa può essere racchiusa tra doppi apici e i nomi al suo interno vanno separati con una virgola. Inoltre, se il nome che indica l'opzione lunga è seguito dai due punti, questa accetta un parametro obbligatorio; se è seguito da una coppia di doppi punti, accetta un parametro facoltativo.
-a|--alternative
Vengono riconosciute le opzioni lunghe nello stile XF86, quindi con un singolo trattino iniziale.
-n|--name progname
Imposta il nome dello script al contenuto della variabile progname.
-q|--quiet
L'output degli errori da parte di getopt è disabilitato.
-Q|--quiet-output
Non viene prodotto l'output di getopt, ovvero la stringa normalizzata dei parametri passati allo script, ma gli errori incontrati nel parsing vengono ancora riportati.
Esempi di chiamate al comando
I seguenti esempi d'uso mostrano come chiamare getopt facendo riferimento, rispettivamente, alle tre sintassi viste:
getopt "hf:d::" "$@"
Con questa chiamata, getopt potrà accettare l'opzione 'h' senza parametro, l'opzione 'f' con un parametro obbligatorio e l'opzione 'd' con un parametro facoltativo.
getopt -a -l "help,file:,dir::" -- "hf:d::" "$@"
Ora, getopt accetta anche le opzioni nella versione lunga: 'help' senza parametro, 'file' con un parametro obbligatorio e 'dir' con un parametro facoltativo.
getopt getopt -l "help,file:dir::" -o "hf:d::" -a -- "$@"
Qui getopt accetta le stesse opzioni del caso precedente, ma queste possono essere indicate anche nello stile XF86.
È importante sottolineare che, negli argomenti passati allo script, opzioni e relativi parametri rispettano le seguenti regole:
- Se un'opzione corta accetta un parametro obbligatorio, opzione e parametro possono essere scritti attaccati o separati da uno spazio. Se il parametro è facoltativo, devono essere scritti attaccati.
- Se un'opzione lunga accetta un parametro obbligatorio, opzione e parametro possono solo essere separati da uno spazio o dal carattere '='. Se il parametro è obbligatorio, devono essere separati dal carattere '='.
- Le opzioni corte possono essere raggruppate e scritte in qualsiasi ordine, con l'accortezza di lasciare accoppiate ai propri parametri quelle che li prevedono.
getopt riconosce qualsiasi abbreviazione non ambigua delle opzioni nel formato lungo. Facendo riferimento agli esempi precedenti, l'opzione '--fi' sarà quindi riconosciuta come --file nel caso non ci sia rischio di ambiguità con altre opzioni.
Esempio d'uso
Lo script che segue accetta l'opzione 'a' senza parametro, l'opzione 'b' con parametro obbligatorio e l'opzione 'c' con parametro facoltativo. Sono accettate anche le rispettive varianti lunghe 'a-lunga', 'b-lunga' e 'c-lunga' nello stile Gnu' (con due trattini come prefisso). Supponendo di aver salvato lo script con il nome script_di_prova_getopt.sh, di seguito viene mostrata una lista di differenti modi di chiamarlo e alcuni dei rispettivi output prodotti:
visualizza come è strutturata una versione canonica dei parametri prodotta da L'istruzione sostituisce i parametri posizionali passati allo script con la stringa PARSED, che è la loro versione Il comando shift viene utilizzato all'interno del costrutto
Il comando
È in grado di fare il parsing solo delle opzioni corte. Se lo script prevede l'uso di opzioni lunghe, sia nello
La sintassi del comando è: in cui Parametro Descrizione optstring È una stringa che istruisce il comando getopts relativamente a quali opzioni aspettarsi e quando siano previsti i relativi parametri. varname È una stringa che rappresenta il nome della variabile della shell in cui il comando getopts inserisce il valore delle opzioni lette. args È una stringa opzionale. Di default getopts fa il parsing dei parametri posizionali, cioè della stringa $@; se è presente una stringa args, farà il parsing dei parametri contenuti in quest'ultima. Come visto nella tabella, il comando Se l'opzione prevede un parametro ad essa associato, il carattere associato all'opzione in Il comando Se, ad esempio, volessimo che Per il suo funzionamento, Variabile Descrizione OPTIND È una variabile della shell, che contiene l'indice del parametro posizionale del prossimo argomento da processare. Viene modificata da getopts, che la usa per tenere traccia del proprio stato. Torna utile anche per poter fare uno shift dei parametri posizionali, dopo averli analizzati con getopts. OPTARG Viene impostata al valore dell'argomento relativo a ogni parametro trovato da getopts. Se l'opzione passata è sconosciuta, viene impostato al valore dell'opzione. OPTERR È una variabile di bash che può assumere il valore 1 o 0, a seconda che si desideri o meno che la shell mostri il messaggio d'errore generato automaticamente da getopts. Di default è impostata ad 1 e ha senso modificarla solo nella modalità verbosa. Non è supportata in shell quali ksh93, mksh, zsh, or dash. La gestione del parametro Modalità verbosa opzione varname è posto uguale al carattere '?' parametro obbligatorio varname è posto uguale al carattere '?' Modalità silenziosa opzione varname è posto uguale al carattere '?' parametro obbligatorio varname è posto uguale al carattere ':'
Il comando viene usato all'interno di un ciclo
Alcuni esempi dell'output generato da questo script sono:
Alcuni esempi dell'output generato da questo script sono:
Nella versione verbosa, il caso \?) gestisce sia un'opzione non valida sia l'assenza di un parametro obbligatorio. La stampa dell'errore è gestita direttamente dal comando L'istruzione
#! /bin/bash
getopt --test > /dev/null
if [[ $? -ne 4 ]]; then
echo "La versione di getopt non è quella del pacchetto utils-linux"
exit 1
fi
OPZIONI_CORTE=ab:c::
OPZIONI_LUNGHE=a-lunga,b-lunga:,c-lunga::
TEMP=$(getopt --options=$OPZIONI_CORTE --longoptions=$OPZIONI_LUNGHE --name "script_di_prova.sh" -- "$@")
if [[ $? -ne 0 ]]; then
echo "getopt ha fallito il parsing"
exit 2
fi
echo "Versione canonica dei parametri prodotta da getopt: "$TEMP""
eval set -- "$TEMP"
while true ; do
case "$1" in
-a|--a-lunga)
echo "Opzione '$1', senza argomento."
shift
;;
-b|--b-lunga)
echo "Opzione '$1', con argomento '$2'."
shift 2
;;
-c|--c-lunga)
case "$2" in
"")
echo "Opzione '$1', senza argomento."
shift 2
;;
*)
echo "Option c, con argomento '$2'."
shift 2
;;
esac
;;
--)
shift
break
;;
*)
echo "Errore interno!"
exit ;;
esac
done
echo "Argomenti rimanenti:"
for i in "$@"; do
echo '--> '"'$i'"
done
$ ./script_di_prova_getopt.sh -a foo
Versione canonica dei parametri prodotta da getopt: -a -- 'foo'
Opzione '-a', senza argomento.
Argomenti rimanenti:
--> 'foo'
L'argomento 'foo' non viene associato all'opzione 'a', ma interpretato come argomento a se stante.$ ./script_di_prova_getopt.sh -b 5 foo
Versione canonica dei parametri prodotta da getopt: -b '5' -- 'foo'
Opzione '-b', con argomento '5'.
Argomenti rimanenti:
--> 'foo'
Per 'foo' si ha lo stesso comportamento del comando precedente, mentre l'argomento '5' viene associato all'opzione '-b'. Visto che per questa opzione il parametro è obbligatorio, si può usare la sintassi equivalente '-b5'.$ ./script_di_prova_getopt.sh -ab 5 foo
in cui, di nuovo, '-b' e '5' possono essere scritti attaccati.$ ./script_di_prova_getopt.sh foo -b5 -a
e a tutte le altre combinazioni consistenti con la sintassi descritta precedentemente.$ ./script_di_prova_getopt.sh --b-lunga 5
e$ ./script_di_prova_getopt.sh --b-lunga=5
$ ./script_di_prova_getopt.sh -c6
$ ./script_di_prova_getopt.sh --c-lunga=6
Considerazioni sull'esempio d'uso
getopt, ma ai fini del funzionamento dello script è superflua.echo "Versione canonica dei parametri prodotta da getopt: "$TEMP" "
eval set -- "$TEMP"
getopts
Pro
getopts è un built-in della shell. Questo comporta che: Contro
stile GNU sia nello stile XF86, getopts non è la scelta opportuna. Funzionamento
getopts optstring varname [args]
optstring va fatto seguire dal carattere ':'. Quindi, se si vuole aggiungere l'opzione 'f' e a questa si vuole associare un parametro, nella stringa optstring si aggiungerà la sequenza 'f:'
non valida
OPTARG è lasciato vuoto.
non fornito
OPTARG è lasciato vuoto e viene stampato un messaggio d'errore.
non valida
OPTARG è posto uguale all'opzione non valida.
non fornito
OPTARG è posto uguale all'opzioneEsempi d'uso
Modalità verbosa
#!/usr/bin/env bash
while getopts "vg:uf:" option;
do
case $option in
v )
echo "Passata l'opzione: -$option"
echo "Non ha un parametro associato, quindi OPTARG=$OPTARG"
echo "Il valore di OPTIND è $OPTIND"
echo "*** *** ***"
;;
g )
echo "Passata l'opzione: -$option"
echo "Ha un parametro associato, quindi OPTARG=$OPTARG"
echo "Il valore di OPTIND è $OPTIND"
echo "*** *** ***"
;;
\?)
echo "Termino"
exit 1
;;
* )
echo "Opzione non ancora implementata: -$option"
echo "*** *** ***"
;;
esac
done
shift $((OPTIND -1))
echo "Rimangono da analizzare i parametri: $@"
Modalità sileziosa
#!/usr/bin/env bash
while getopts ":vg:uf:" option;
do
case $option in
v )
echo "Passata l'opzione: -$option"
echo "Non ha un parametro associato, quindi OPTARG=$OPTARG"
echo "Il valore di OPTIND è $OPTIND"
echo "*** *** ***"
;;
g )
echo "Passata l'opzione: -$option"
echo "Ha un parametro associato, quindi OPTARG=$OPTARG"
echo "Il valore di OPTIND è $OPTIND"
echo "*** *** ***"
;;
\?)
echo "Opzione non valida: -$OPTARG" >&2
echo "Il valore di OPTIND è $OPTIND" >&2
echo "*** *** ***"
exit 1
;;
: )
echo "L'opzione: -$OPTARG richede un parametro, che non è stato passato" >&2
echo "Il valore di OPTIND è $OPTIND" >&2
echo "*** *** ***"
exit 1
;;
* )
echo "Opzione non ancora implementata: -$option" >&2
exit 1
esac
done
shift $((OPTIND -1))
echo "Rimangono da analizzare i parametri: $@"
Considerazioni sugli esempi d'uso
getopts, che però continua il parsing. Se si desidera che il programma termini la sua esecuzione in questi due casi, deve essere richiesto esplicitamente, ad esempio con il comando exit. Ulteriori risorse