Attenzione! Questa è una Pagina di prova. Le informazioni riportate potrebbero essere incomplete, errate e potenzialmente pericolose. Per contribuire alla realizzazione di questa pagina consultare la discussione di riferimento.

Problemi in questa pagina? Segnalali in questa discussione

Introduzione

Il parsing è la procedura con cui un comando, uno script o più genericamente un programma, analizza le istruzioni che l'utente fornisce quando lo chiama usando il terminale.

Queste istruzioni sono una opportuna combinazione di opzioni e parametri e modificano il comportamento del programma a cui vengono passate.

A esempio, per lanciare il comando ls da terminale una sinossi comune è:

ls -a -l --color=auto file (o /percorso/al/file)

Il comando è composto da una serie di opzioni chiamate argomenti.

Il primo argomento è il nome del comando, mentre i successivi sono indicati col nome di parametri posizionali.

Questi ultimi possono essere suddivisi in alcune categorie logiche:

Il comando precedente si può dattilografare anche così:

ls --color=auto -la percorso 

in cui, tutte le opzioni corte sono state riunite ed è stato cambiato l'ordine di tutte le opzioni.

Non tutti i comandi accettano un ordine casuale delle opzioni.

La difficoltà del parsing è proprio nel riconoscimento delle varie opzioni e parametri, a prescindere dalla loro posizione nella sintassi della chiamata.

Per agevolare questa procedura, sono disponibili due utili comandi da usare nel terminale:

getopt

getopt analizza una stringa di parametri e ne restituisce una versione canonica e standardizzata che può essere analizzata più facilmente. Questa analisi successiva viene eseguita in un ciclo while, all'interno del quale le varie scelte sono effettuate in un costrutto case.

Pro

Contro

Funzionamento

getopt può essere chiamato con tre diverse sintassi. La più semplice è:

getopt optstring parameters

La stringa optsting elenca le opzioni nel formato corto che si possono incontrare durante il parsing. Questa stringa può essere racchiusa tra doppi apici e al suo interno i nomi delle opzioni possono essere elencati senza separatori. Se l'opzione prevede un parametro obbligatorio, il carattere che la indica è seguito dai due punti; se il parametro è opzionale, è seguito da una coppia di doppi punti.
parameters è la stringa degli argomenti su cui operare. Generalmente si pone uguale alla stringa dei parametri posizionali passati allo script, cioè "$@". Se si vuole scrivere 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; le parti racchiuse tra parentesi quadre sono opzionali; 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. Le più importanti sono:

Esempi di chiamate al comando

I seguenti esempi d'uso mostrano come chiamare getopt facendo riferimento, rispettivamente, alle tre sintassi viste:

È importante sottolineare che, negli argomenti passati allo script, opzioni e relativi parametri rispettano le seguenti regole:

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).

#! /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 "prova_getopt.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

if [[ $# != 0 ]]
then
    echo "Argomenti rimanenti:"
    for i in "$@"
    do
        echo "--> '$i'"
    done
fi

Supponendo di aver salvato lo script con il nome prova_getopt.sh, di seguito viene mostrata una lista di differenti modi di chiamarlo e alcuni dei rispettivi output prodotti:

Considerazioni sull'esempio d'uso

getopts

Pro

Contro

Funzionamento

La sintassi del comando è:

getopts optstring varname [args]

in cui

Parametro

Descrizione

optstring

È una stringa che istruisce il comando 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 facoltativa. Di default, il comando fa il parsing dei parametri posizionali, cioè della stringa $@; se è presente una stringa args, farà il parsing dei parametri contenuti in quest'ultima.

getopts viene quindi istruito sulle opzioni e gli eventuali parametri che si può aspettare tramite optstring.
La sintassi di questa stringa è molto semplice.

Quindi, se desideriamo che il comando si aspetti di incontrare nel parsing le opzione 'v' ed 'h' senza parametri associati e l'opzione 'f' con un parametro associato, optstring sarebbe uguale a "vhf:" per la modalità verbosa e uguale a ":vhf:" per quella silenziosa.

Per il suo funzionamento, getopts usa le seguenti variabili:

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

Se è previsto un parametro, viene impostata al valore si quest'ultimo. Se l'opzione non prevede un parametro, è lasciato vuoto. 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 varname e della variabile OPTARG cambia a seconda della modalità in cui si usa il comando ed è riassunta nella seguente tabella:

Modalità verbosa

opzione
non valida

varname è posto uguale al carattere '?'
OPTARG è lasciato vuoto.

parametro obbligatorio
non fornito

varname è posto uguale al carattere '?'
OPTARG è lasciato vuoto e viene stampato un messaggio d'errore.

Modalità silenziosa

opzione
non valida

varname è posto uguale al carattere '?'
OPTARG è posto uguale all'opzione non valida.

parametro obbligatorio
non fornito

varname è posto uguale al carattere ':'
OPTARG è posto uguale all'opzione

Esempi d'uso

Il comando viene generalmente usato all'interno di un ciclo while: a ogni iterazione, legge dalla stringa dei parametri posizionali (o da args se fornito) un'opzione e il suo eventuale parametro; se tutto è corretto, aggiorna le sue variabili interne, secondo quanto visto al punto precedente, e fornisce questi dati all'utente per la loro analisi, che viene svolta all'interno di un costrutto case. Il comando restituisce un exit status uguale a 1, interrompendo il ciclo while, quando incontra il primo parametro opzionale che non corrisponde a una opzione prevista.

Modalità verbosa

Lo script che segue è un esempio di utilizzo del comando nella modalità verbosa. Lo script accetta le opzioni 'a' e 'c' senza parametro e le opzioni 'b' e 'd' con un parametro. Le opzioni 'b' e 'd' non sono implementate, per simulare una situazione frequente nelle fasi iniziali di sviluppo di uno script.

#!/bin/bash

while getopts "ab:cd:" option
do
    case $option in
        a)
            echo "Opzione -$option, senza argomento"
            echo "OPTIND è $OPTIND"
            echo "*** *** ***"
            ;;
        b)
            echo "Opzione -$option, con argomento '"$OPTARG"'"
            echo "OPTIND è $OPTIND"
            echo "*** *** ***"
            ;;
        \?)
            echo "OPTIND è $OPTIND" >&2
            echo "Termino" >&2
            exit 1
            ;;
        *) 
            echo "Opzione non ancora implementata: -$option"
            echo "OPTIND è $OPTIND"
            echo "*** *** ***"
            ;;
    esac
done

shift $((OPTIND - 1))

if [[ $# -ne 0 ]]
then
    echo "Rimangono da analizzare i parametri:"
    for i in "$@"
    do
        echo "--> '$i'"
    done
fi

Supponendo di aver salvato lo script con il nome prova_getopts_verboso.sh, alcuni esempi dell'output generato da questo script sono:

Modalità sileziosa

Lo script seguente è l'analogo del precedente, ma in modalità silenziosa:

#!/usr/bin/env bash

while getopts ":ab:cd:" option;
do
    case $option in
        a)
            echo "Opzione -$option, senza argomento"
            echo "OPTIND è $OPTIND"
            echo "*** *** ***"
            ;;
        b)
            echo "Opzione -$option, con argomento '"$OPTARG"'"
            echo "OPTIND è $OPTIND"
            echo "*** *** ***"
            ;;
        \?)
            echo "Opzione non valida: -$OPTARG" >&2
            echo "OPTIND è $OPTIND" >&2
            echo "Termino" >&2
            exit 1
            ;;
        : )
            echo "-$OPTARG richede un parametro, che non è stato passato" >&2
            echo "OPTIND è $OPTIND" >&2
            echo "Termino" >&2
            exit 1
            ;;
        *)
            echo "Opzione non ancora implementata: -$option"
            echo "OPTIND è $OPTIND"
            echo "*** *** ***"
    esac
done

shift $((OPTIND -1))

if [[ $# -ne 0 ]]
then
    echo "Rimangono da analizzare i parametri:"
    for i in "$@"
    do
        echo "--> '$i'"
    done
fi

Differenze dallo script precedente ci sono solo per opzioni non valide e parametri obbligatori non passati. Se lo script è stato salvato col nome prova_getopts_silenzioso.sh, si ha rispettivamente:

Considerazioni sugli esempi d'uso

Ulteriori risorse


CategoryNuoviDocumenti

leon-wells/ParsingDellaRigaDiComandoRevo (l'ultima modifica è del 29/11/2021 16.32.46, fatta da wilecoyote)