Padroneggiare l'Analisi degli Argomenti in Bash per Script Potenti

Analizza gli argomenti di Bash con parametri posizionali, getopts, cicli per opzioni lunghe, valori predefiniti e messaggi di errore chiari.

Padroneggiare l'Analisi degli Argomenti in Bash per Script Potenti

Gli argomenti da riga di comando rendono flessibili i tuoi script Bash. Quando l'analisi degli argomenti in Bash è debole, ti ritrovi a modificare le variabili all'interno dello script ogni volta che hai bisogno di un file, host o modalità diversa.

Questa guida ti mostra come gestire argomenti posizionali, opzioni brevi con getopts e opzioni lunghe con un ciclo while/case. L'obiettivo è uno script che rifiuti input errati precocemente e ti dica esattamente come eseguirlo.

Le Basi: Argomenti Posizionali

Prima di affrontare flag e opzioni nominate, è cruciale capire come Bash gestisce argomenti semplici e sequenziali.

Variabile Descrizione Esempio se chiamato come ./script.sh foo bar
$0 Il nome dello script stesso ./script.sh
$1, $2, ... Il primo, secondo, ecc., argomento posizionale foo, bar
$# Il conteggio degli argomenti posizionali 2
$@ Tutti gli argomenti posizionali, trattati come stringhe separate foo bar
$* Tutti gli argomenti posizionali, trattati come un'unica stringa foo bar

Esempio: Controllo Posizionale Semplice

#!/bin/bash

if [ "$#" -ne 2 ]; then
    echo "Utilizzo: $0 <file_sorgente> <directory_destinazione>"
    exit 1
fi

SOURCE="$1"
DESTINATION="$2"

echo "Copia di $SOURCE in $DESTINATION..."
# cp "$SOURCE" "$DESTINATION"

Analisi Standard con getopts per Opzioni Brevi

Per script professionali che richiedono opzioni come -v (verbose) o -f <file>, l'utilità integrata getopts è il metodo canonico e più affidabile in Bash puro. È progettata specificamente per opzioni brevi (a carattere singolo).

Come Funziona getopts

getopts legge le opzioni in sequenza, impostando la variabile designata (di solito OPT) sull'opzione trovata e inserendo il valore di qualsiasi argomento (se richiesto) nella variabile OPTARG.

  • Stringa di Opzioni (OPTSTRING): Definisce le opzioni valide. Se un'opzione richiede un argomento (ad es., -f nomefile), segui il carattere con due punti (:). Esempio: vho: permette -v, -h e -o che richiede un valore.
  • OPTIND: Un indice Bash interno che tiene traccia del prossimo argomento da elaborare. Deve essere inizializzato a 1 (che è il valore predefinito, ma a volte resettato in script complessi).

Modello Pratico per getopts

Questo modello gestisce tre opzioni: -v (flag), -h (flag) e -f (opzione che richiede un valore).

#!/bin/bash

# --- Valori Predefiniti ---
VERBOSE=0
FILENAME="default.txt"

# --- Funzione di Utilizzo ---
usage() {
    echo "Utilizzo: $0 [-v] [-h] [-f <file>] <input>"
    exit 1
}

# --- Ciclo di Analisi degli Argomenti ---
while getopts ":vhf:" OPT; do
    case "$OPT" in
        v)
            VERBOSE=1
            echo "Modalità verbose abilitata."
            ;;
        h)
            usage
            ;;
        f)
            # OPTARG contiene l'argomento fornito a -f
            FILENAME="$OPTARG"
            echo "Nome file di output impostato su: $FILENAME"
            ;;
        \?)
            # Gestisce opzioni non riconosciute
            echo "Errore: Opzione non valida -$OPTARG" >&2
            usage
            ;;
        :)
            # Gestisce argomenti mancanti per opzioni che ne richiedono uno (ad es., -f senza nomefile)
            echo "Errore: L'opzione -$OPTARG richiede un argomento." >&2
            usage
            ;;
    esac
done

# --- Spostamento degli Argomenti Posizionali ---
# Dopo che getopts termina, OPTIND contiene l'indice del primo argomento non opzione.
# Usiamo shift per scartare tutte le opzioni analizzate, lasciando solo gli argomenti posizionali ($1, $2, ecc.).
shift $((OPTIND - 1))

# Verifica se l'argomento posizionale richiesto (INPUT) è presente
INPUT_DATA="$1"
if [ -z "$INPUT_DATA" ]; then
    echo "Errore: Dati di input richiesti."
    usage
fi

echo "---"
echo "Elaborazione input: $INPUT_DATA"
echo "Stato verbose: $VERBOSE"

Suggerimento: Usa sempre shift $((OPTIND - 1)) immediatamente dopo il ciclo while getopts per separare pulitamente le opzioni dagli argomenti posizionali rimanenti.

Gestione delle Opzioni Lunghe come --option

Il getopts integrato di Bash puro supporta solo opzioni brevi. Per gestire opzioni lunghe moderne (ad es., --verbose, --output-file=data.log), devi implementare un ciclo di analisi personalizzato usando while e case con il comando shift.

Questo metodo richiede una gestione degli argomenti più esplicita.

Analizzatore Personalizzato per Opzioni Lunghe

#!/bin/bash

# --- Valori Predefiniti ---
VERBOSE=0
OUTPUT_FILE=""

# Funzione personalizzata per mostrare l'utilizzo (omessa per brevità)
# usage() { ... }

while [ "$#" -gt 0 ]; do
    case "$1" in
        --verbose)
            VERBOSE=1
            shift
            ;;
        --output-file)
            # Richiede due shift: uno per il flag, uno per il valore
            if [ -z "${2:-}" ]; then
                echo "Errore: --output-file richiede un valore."
                exit 1
            fi
            OUTPUT_FILE="$2"
            shift 2
            ;;
        --help)
            usage
            ;;
        -*)
            echo "Errore: Opzione sconosciuta $1" >&2
            exit 1
            ;;
        *)
            # Trovato il primo argomento posizionale, ferma l'analisi delle opzioni
            break
            ;;
    esac
done

# Gli argomenti rimanenti sono ora disponibili come $1, $2, ecc.
# ... La logica dello script continua ...

if [ "$OUTPUT_FILE" ]; then
    echo "Dati reindirizzati a $OUTPUT_FILE"
fi

Se il tuo script accetta argomenti posizionali dopo le opzioni, continua l'analisi fino a raggiungere -- o il primo argomento non opzione. Una convenzione comune è lasciare che -- significhi "ferma l'analisi delle opzioni ora":

while [ "$#" -gt 0 ]; do
    case "$1" in
        --)
            shift
            break
            ;;
        --verbose)
            VERBOSE=1
            shift
            ;;
        *)
            break
            ;;
    esac
done

Avanzato: Gestione delle Opzioni Lunghe Chiave-Valore (--key=value)

Se preferisci lo stile UNIX standard in cui gli argomenti vengono passati usando un segno di uguale, devi usare la sostituzione dei parametri per dividere l'argomento.

while [ "$#" -gt 0 ]; do
    case "$1" in
        --limit=*)
            LIMIT_VAL="${1#*=}" # Rimuovi tutto fino a e incluso '='
            echo "Limite impostato su: $LIMIT_VAL"
            shift
            ;;
        # ... altre opzioni ...
    esac
done

Migliori Pratiche per Script Robusto

A. Combinare Opzioni Brevi e Lunghe

Per massima flessibilità, gli script esperti spesso combinano l'affidabilità di getopts per le opzioni brevi con il ciclo personalizzato while/case per le opzioni lunghe. Il ciclo delle opzioni lunghe viene eseguito per primo, consumando i flag lunghi, e poi gli argomenti rimanenti (incluse le opzioni brevi) vengono elaborati da getopts.

Tuttavia, un modello più pulito e comune è elaborare tutti gli argomenti in un unico ciclo personalizzato robusto che cerca sia -o che --option, spostandosi di conseguenza.

B. Gestione degli Errori e Utilizzo

Fornisci sempre una funzione usage chiara che spieghi gli argomenti e le opzioni richieste dallo script. Questa funzione dovrebbe essere chiamata quando:

  1. L'utente richiede aiuto (ad es., -h o --help).
  2. Un argomento richiesto è mancante.
  3. Viene fornita un'opzione non valida o sconosciuta.

Assicurati che lo script esca con uno stato diverso da zero in caso di errore (exit 1) e invii i messaggi di errore allo Standard Error (>&2).

C. Valori Predefiniti

Inizializza tutte le variabili di configurazione all'inizio dello script con valori predefiniti sensati. Questo rende il tuo script prevedibile anche se non vengono passati argomenti opzionali.

# Inizializza sempre le variabili prima dell'analisi
LOG_LEVEL="info"
FORCE=0

Conclusione

Usa argomenti posizionali per valori semplici richiesti, getopts per opzioni brevi portabili e un ciclo personalizzato while/case quando hai bisogno di opzioni lunghe. Testa valori mancanti, flag sconosciuti e argomenti con spazi prima di fidarti dello script nell'automazione.