Beherrschung der Bash-Argumentanalyse für leistungsstarke Skripte

Analysieren Sie Bash-Argumente mit Positionsparametern, getopts, Long-Option-Schleifen, Standardwerten und klaren Nutzungsfehlern.

Beherrschung der Bash-Argumentanalyse für leistungsstarke Skripte

Kommandozeilenargumente machen Ihre Bash-Skripte flexibel. Wenn die Bash-Argumentanalyse schwach ist, müssen Sie jedes Mal Variablen im Skript bearbeiten, wenn Sie eine andere Datei, einen anderen Host oder einen anderen Modus benötigen.

Diese Anleitung zeigt Ihnen, wie Sie Positionsargumente, kurze Optionen mit getopts und lange Optionen mit einer while/case-Schleife handhaben. Das Ziel ist ein Skript, das schlechte Eingaben frühzeitig ablehnt und Ihnen genau sagt, wie Sie es ausführen sollen.

Die Grundlagen: Positionsargumente

Bevor Sie sich mit Flags und benannten Optionen befassen, ist es entscheidend zu verstehen, wie Bash einfache, sequenzielle Argumente behandelt.

Variable Beschreibung Beispiel, wenn aufgerufen als ./script.sh foo bar
$0 Der Name des Skripts selbst ./script.sh
$1, $2, ... Das erste, zweite usw. Positionsargument foo, bar
$# Die Anzahl der Positionsargumente 2
$@ Alle Positionsargumente, behandelt als separate Zeichenfolgen foo bar
$* Alle Positionsargumente, behandelt als eine einzelne Zeichenfolge foo bar

Beispiel: Einfache Positionsprüfung

#!/bin/bash

if [ "$#" -ne 2 ]; then
    echo "Verwendung: $0 <quelldatei> <zielverzeichnis>"
    exit 1
fi

QUELLE="$1"
ZIEL="$2"

echo "Kopiere $QUELLE nach $ZIEL..."
# cp "$QUELLE" "$ZIEL"

Standard-Parsing mit getopts für kurze Optionen

Für professionelle Skripte, die Optionen wie -v (verbose) oder -f <datei> erfordern, ist das integrierte Dienstprogramm getopts die kanonische und zuverlässigste Methode in reinem Bash. Es wurde speziell für kurze (einzelne Zeichen) Optionen entwickelt.

Wie getopts funktioniert

getopts liest Optionen nacheinander, setzt die festgelegte Variable (normalerweise OPT) auf die gefundene Option und platziert den Wert eines Arguments (falls erforderlich) in der Variablen OPTARG.

  • Optionszeichenfolge (OPTSTRING): Definiert gültige Optionen. Wenn eine Option ein Argument erfordert (z. B. -f dateiname), folgen Sie dem Zeichen mit einem Doppelpunkt (:). Beispiel: vho: erlaubt -v, -h und -o, das einen Wert erfordert.
  • OPTIND: Ein interner Bash-Index, der das nächste zu verarbeitende Argument verfolgt. Es muss auf 1 initialisiert werden (was der Standard ist, aber manchmal in komplexen Skripten zurückgesetzt wird).

Praktische getopts-Vorlage

Diese Vorlage behandelt drei Optionen: -v (Flag), -h (Flag) und -f (Option, die einen Wert erfordert).

#!/bin/bash

# --- Standardwerte ---
VERBOSE=0
DATEINAME="standard.txt"

# --- Verwendungsfunktion ---
verwendung() {
    echo "Verwendung: $0 [-v] [-h] [-f <datei>] <eingabe>"
    exit 1
}

# --- Argument-Parsing-Schleife ---
while getopts ":vhf:" OPT; do
    case "$OPT" in
        v)
            VERBOSE=1
            echo "Ausführlicher Modus aktiviert."
            ;;
        h)
            verwendung
            ;;
        f)
            # OPTARG enthält das für -f bereitgestellte Argument
            DATEINAME="$OPTARG"
            echo "Ausgabedateiname festgelegt auf: $DATEINAME"
            ;;
        \?)
            # Behandelt nicht erkannte Optionen
            echo "Fehler: Ungültige Option -$OPTARG" >&2
            verwendung
            ;;
        :)
            # Behandelt fehlende Argumente für Optionen, die eines erfordern (z. B. -f ohne Dateinamen)
            echo "Fehler: Option -$OPTARG erfordert ein Argument." >&2
            verwendung
            ;;
    esac
done

# --- Verschieben von Positionsargumenten ---
# Nachdem getopts fertig ist, enthält OPTIND den Index des ersten Nicht-Options-Arguments.
# Wir verwenden shift, um alle geparsten Optionen zu verwerfen und nur die Positionsargumente ($1, $2, etc.) zu behalten.
shift $((OPTIND - 1))

# Prüfen, ob das erforderliche Positionsargument (EINGABE) vorhanden ist
EINGABE_DATEN="$1"
if [ -z "$EINGABE_DATEN" ]; then
    echo "Fehler: Eingabedaten erforderlich."
    verwendung
fi

echo "---"
echo "Verarbeite Eingabe: $EINGABE_DATEN"
echo "Ausführlichkeitsstatus: $VERBOSE"

Tipp: Verwenden Sie immer shift $((OPTIND - 1)) unmittelbar nach der while getopts-Schleife, um Optionen sauber von den verbleibenden Positionsargumenten zu trennen.

Umgang mit langen Optionen wie --option

Das in Bash integrierte getopts unterstützt nur kurze Optionen. Um moderne lange Optionen (z. B. --verbose, --output-file=data.log) zu handhaben, müssen Sie eine benutzerdefinierte Parsing-Schleife mit while und case zusammen mit dem Befehl shift implementieren.

Diese Methode erfordert eine explizitere Argumentverwaltung.

Benutzerdefinierter Parser für lange Optionen

#!/bin/bash

# --- Standardwerte ---
VERBOSE=0
AUSGABEDATEI=""

# Benutzerdefinierte Funktion zur Anzeige der Verwendung (aus Gründen der Kürze weggelassen)
# verwendung() { ... }

while [ "$#" -gt 0 ]; do
    case "$1" in
        --verbose)
            VERBOSE=1
            shift
            ;;
        --output-file)
            # Erfordert zwei Verschiebungen: eine für das Flag, eine für den Wert
            if [ -z "${2:-}" ]; then
                echo "Fehler: --output-file erfordert einen Wert."
                exit 1
            fi
            AUSGABEDATEI="$2"
            shift 2
            ;;
        --help)
            verwendung
            ;;
        -*)
            echo "Fehler: Unbekannte Option $1" >&2
            exit 1
            ;;
        *)
            # Erstes Positionsargument gefunden, Parsing von Optionen beenden
            break
            ;;
    esac
done

# Verbleibende Argumente sind jetzt als $1, $2, etc. verfügbar.
# ... Skriptlogik wird fortgesetzt ...

if [ "$AUSGABEDATEI" ]; then
    echo "Daten umgeleitet nach $AUSGABEDATEI"
fi

Wenn Ihr Skript Positionsargumente nach Optionen akzeptiert, fahren Sie mit dem Parsing fort, bis Sie auf -- oder das erste Nicht-Options-Argument stoßen. Eine gängige Konvention ist, -- zu verwenden, um "jetzt mit dem Parsen von Optionen aufhören" zu signalisieren:

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

Fortgeschritten: Umgang mit Schlüssel-Wert-Langoptionen (--key=value)

Wenn Sie den Standard-UNIX-Stil bevorzugen, bei dem Argumente mit einem Gleichheitszeichen übergeben werden, müssen Sie die Parametersubstitution verwenden, um das Argument aufzuteilen.

while [ "$#" -gt 0 ]; do
    case "$1" in
        --limit=*)
            LIMIT_WERT="${1#*=}" # Entfernt alles bis einschließlich '='
            echo "Limit gesetzt auf: $LIMIT_WERT"
            shift
            ;;
        # ... andere Optionen ...
    esac
done

Best Practices für robustes Scripting

A. Kombinieren von kurzen und langen Optionen

Für maximale Flexibilität kombinieren erfahrene Skriptersteller oft die Zuverlässigkeit von getopts für kurze Optionen mit der benutzerdefinierten while/case-Schleife für lange Optionen. Die lange Optionsschleife läuft zuerst, verbraucht lange Flags, und dann werden die verbleibenden Argumente (einschließlich kurzer Optionen) von getopts verarbeitet.

Ein saubereres, gängiges Muster besteht jedoch darin, alle Argumente in einer robusten benutzerdefinierten Schleife zu verarbeiten, die sowohl nach -o als auch nach --option sucht und entsprechend verschiebt.

B. Fehlerbehandlung und Verwendung

Stellen Sie immer eine klare verwendung-Funktion bereit, die die erforderlichen Argumente und Optionen des Skripts erklärt. Diese Funktion sollte aufgerufen werden, wenn:

  1. Der Benutzer Hilfe anfordert (z. B. -h oder --help).
  2. Ein erforderliches Argument fehlt.
  3. Eine ungültige oder unbekannte Option angegeben wird.

Stellen Sie sicher, dass das Skript bei einem Fehler mit einem Nicht-Null-Status beendet wird (exit 1) und Fehlermeldungen an die Standardfehlerausgabe (>&2) ausgibt.

C. Standardwerte

Initialisieren Sie alle Konfigurationsvariablen am Anfang des Skripts mit sinnvollen Standardwerten. Dies macht Ihr Skript vorhersagbar, auch wenn keine optionalen Argumente übergeben werden.

# Variablen immer vor dem Parsen initialisieren
LOG_LEVEL="info"
FORCE=0

Fazit

Verwenden Sie Positionsargumente für einfache erforderliche Werte, getopts für portable kurze Optionen und eine benutzerdefinierte while/case-Schleife, wenn Sie lange Optionen benötigen. Testen Sie fehlende Werte, unbekannte Flags und Argumente mit Leerzeichen, bevor Sie dem Skript in der Automatisierung vertrauen.