DevOps-bootcamp · Lektion

Parsa flaggor och argument med getopts

Implementera professionella kommandoradsgränssnitt med getopts för korta alternativ, obligatoriska argument och användningsmeddelanden.

Lektion 3 av 413 steg

Parsa flaggor och argument med getopts är en gratis lektion i DevOps-bootcamp på CoddyKit. Detta är lektion 3 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för DevOps-bootcamp, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i DevOps-bootcamp innehåller totalt 4 lektioner.

Varför getopts finns

Alla verkliga skript behöver förr eller senare ta emot flaggor som -v, -o output.txt eller -n 5. Att tolka dessa manuellt med $1, $2… blir snabbt skört.

getopts är det inbyggda verktyget enligt POSIX-standarden som hanterar korta flaggor (-a, -b) på ett tillförlitligt sätt, även flaggor som tar ett argument. Det är inbyggt i alla POSIX-skal, så inga beroenden krävs.

  • Hanterar kombinerade flaggor: -vn 5 = -v -n 5
  • Rapporterar okända flaggor på ett kontrollerat sätt
  • Anger automatiskt standardvariablerna OPTIND och OPTARG

I den här lektionen bygger ni ett komplett, professionellt CLI-gränssnitt med getopts från grunden.

Syntaxen för getopts

Grundsyntaxen är en while-loop som anropar getopts vid varje iteration:

while getopts "optstring" varname; do
  case "$varname" in
    ...
  esac
done
  • optstring — en sträng som listar varje accepterad flaggbokstav. Ett kolon efter en bokstav betyder att flaggan kräver ett argument.
  • varname — tar emot den aktuella flaggbokstaven vid varje iteration.
  • OPTARG — sätts automatiskt till argumentets värde när ett kolon följer efter bokstaven.
  • OPTIND — indexet för nästa argument som ska behandlas; använd shift $((OPTIND - 1)) efter loopen för att göra återstående positionsparametrar tillgängliga.
#!/usr/bin/env bash
# Minimal skeleton — shows the loop structure
while getopts 'vn:' opt; do
  case "$opt" in
    v) echo "Verbose mode on" ;;
    n) echo "Count = $OPTARG" ;;
    ?) echo "Unknown option: -$OPTARG" >&2; exit 1 ;;
  esac
done

Definiera en optstring

optstring är en kompakt deklaration av CLI-gränssnittets kontrakt. Varje tecken representerar en accepterad flagga.

  • 'abc' — accepterar -a, -b, -c (inga argument)
  • 'a:bc' — -a kräver ett argument; -b och -c gör det inte
  • ':abc' — ett inledande kolon aktiverar tyst felläge (skriptet hanterar felaktiga flaggor i stället för att skalet skriver ut ett meddelande)

Tyst läge rekommenderas i produktionsskript eftersom det ger full kontroll över felmeddelanden och avslutningskoder.

#!/usr/bin/env bash
# optstring ':o:vq'
# -o  requires an argument (output file)
# -v  verbose flag (no argument)
# -q  quiet flag  (no argument)
# Leading ':' = silent error mode

while getopts ':o:vq' opt; do
  case "$opt" in
    o) OUTPUT="$OPTARG" ;;
    v) VERBOSE=1 ;;
    q) QUIET=1 ;;
    :) echo "Error: -$OPTARG requires an argument" >&2; exit 1 ;;
    \?) echo "Error: unknown option -$OPTARG" >&2; exit 1 ;;
  esac
done
echo "OUTPUT=$OUTPUT  VERBOSE=$VERBOSE  QUIET=$QUIET"

OPTARG och obligatoriska argument

När en flagga följs av ett kolon i optstring lagrar getopts dess värde i OPTARG. Användaren kan skriva argumentet antingen med eller utan mellanslag:

  • -o report.txt
  • -oreport.txt

Båda formerna tolkas identiskt. Det här är en av de viktigaste fördelarna jämfört med manuell tolkning med $1/shift.

I tyst läge (ett inledande ':' i optstring) gör ett saknat argument att getopts sätter varname till : och OPTARG till flaggbokstaven — perfekt för ett riktat felmeddelande.

#!/usr/bin/env bash
# Demonstrate OPTARG with a file-processing script

while getopts ':i:o:' opt; do
  case "$opt" in
    i) INPUT="$OPTARG" ;;
    o) OUTPUT="$OPTARG" ;;
    :) echo "Error: option -$OPTARG needs a value" >&2; exit 1 ;;
    \?) echo "Error: unknown flag -$OPTARG" >&2; exit 1 ;;
  esac
done

echo "Input  : ${INPUT:-<not set>}"
echo "Output : ${OUTPUT:-<not set>}"

Skifta förbi flaggor med OPTIND

När getopts är klar innehåller OPTIND indexet för det första argumentet som inte är en flagga. Använd shift för att ta bort alla behandlade flaggor, så att $1, $2… refererar till de återstående positionsparametrarna (till exempel filnamn).

Idiomets form är alltid:

shift $((OPTIND - 1))

Efter skiftningen innehåller $@ endast de argument som inte var flaggor — kommandots operander.

#!/usr/bin/env bash
# Shows OPTIND shift and leftover positional args

VERBOSE=0
while getopts ':vn:' opt; do
  case "$opt" in
    v) VERBOSE=1 ;;
    n) COUNT="$OPTARG" ;;
    :) echo "Error: -$OPTARG requires an argument" >&2; exit 1 ;;
    \?) echo "Error: unknown option -$OPTARG" >&2; exit 1 ;;
  esac
done
shift $((OPTIND - 1))

echo "VERBOSE=$VERBOSE  COUNT=${COUNT:-1}"
echo "Remaining args: $*"

Skriv en usage-funktion

Ett professionellt skript har alltid en usage()-funktion som skriver ut ett hjälpmeddelande och avslutar. Konventionen är:

  • Skriv till stderr (fd 2) så att meddelandet inte blandas in i rörlagrade utdata
  • Avsluta med koden 0 för -h / --help och med koden 1 vid ogiltig användning
  • Anropa usage 1 vid fel och usage 0 från hanteraren för -h
#!/usr/bin/env bash

usage() {
  cat >&2 <<EOF
Usage: $(basename "$0") [-v] [-n COUNT] [-o FILE] [FILE...]

Options:
  -v          Verbose output
  -n COUNT    Repeat COUNT times (default: 1)
  -o FILE     Write output to FILE
  -h          Show this help
EOF
  exit "${1:-0}"
}

while getopts ':vn:o:h' opt; do
  case "$opt" in
    v) VERBOSE=1 ;;
    n) COUNT="$OPTARG" ;;
    o) OUTFILE="$OPTARG" ;;
    h) usage 0 ;;
    :) echo "Error: -$OPTARG requires a value" >&2; usage 1 ;;
    \?) echo "Error: unknown option -$OPTARG" >&2; usage 1 ;;
  esac
done
shift $((OPTIND - 1))
echo "Parsed OK — verbose=${VERBOSE:-0} count=${COUNT:-1} out=${OUTFILE:--}"

Standardvärden och validering

Validera och ange standardvärden efter tolkningen, innan något verkligt arbete utförs. Håll tolkningsfasen (loopen) åtskild från logikfasen. Då blir båda delarna lättare att läsa och testa.

  • Använd ${VAR:-default} för standardvärden inline
  • Validera numeriska argument med ett reguljärt uttryck eller en aritmetisk kontroll
  • Kontrollera att obligatoriska flaggor faktiskt angavs
#!/usr/bin/env bash

usage() { echo "Usage: $(basename "$0") -n COUNT [-v]" >&2; exit 1; }

VERBOSE=0
COUNT=''

while getopts ':n:v' opt; do
  case "$opt" in
    n) COUNT="$OPTARG" ;;
    v) VERBOSE=1 ;;
    :) echo "Error: -$OPTARG needs a value" >&2; usage ;;
    \?) echo "Error: -$OPTARG unknown" >&2; usage ;;
  esac
done
shift $((OPTIND - 1))

# Validation phase
[[ -z "$COUNT" ]] && { echo "Error: -n COUNT is required" >&2; usage; }
[[ "$COUNT" =~ ^[0-9]+$ ]] || { echo "Error: COUNT must be a positive integer" >&2; usage; }

for (( i=1; i<=COUNT; i++ )); do
  [[ $VERBOSE -eq 1 ]] && echo "Iteration $i of $COUNT"
  echo "Hello, world!"
done

Kombinera flaggor på kommandoraden

getopts hanterar automatiskt kombinerade korta flaggor som skrivs utan mellanslag, vilket är standardkonventionen i Unix:

  • -v -q motsvarar -vq
  • -n 5 -v motsvarar -n5 -v eller -vn5

Ni behöver inte skriva någon extra kod för att stödja detta — getopts itererar automatiskt genom varje tecken i en kombinerad flaggsträng. Det här är ytterligare ett viktigt skäl att använda getopts i stället för manuell tolkning.

#!/usr/bin/env bash
# Test combined flag parsing
# Run as:  bash script.sh -vq -n3

VERBOSE=0; QUIET=0; COUNT=1

while getopts ':vqn:' opt; do
  case "$opt" in
    v) VERBOSE=1 ;;
    q) QUIET=1 ;;
    n) COUNT="$OPTARG" ;;
    :) echo "Error: -$OPTARG needs value" >&2; exit 1 ;;
    \?) echo "Error: unknown -$OPTARG" >&2; exit 1 ;;
  esac
done
shift $((OPTIND - 1))

echo "verbose=$VERBOSE quiet=$QUIET count=$COUNT"

Hantera avgränsaren med dubbla bindestreck

Unix-kommandon accepterar -- (dubbla bindestreck) som en uttrycklig signal om att flaggtolkningen ska stoppas. Allt efter -- behandlas som ett positionsargument, även om det ser ut som en flagga.

getopts stannar automatiskt när det stöter på --. Efter shift $((OPTIND - 1)) är de dubbla bindestrecken borta och $@ innehåller endast operanderna.

Detta är viktigt för skript som arbetar med filnamn som kan börja med ett bindestreck, till exempel:

myscript.sh -v -- -strangefile.txt
#!/usr/bin/env bash
# Demonstrate -- separator
# Run as:  bash script.sh -v -- file1.txt -oddname.txt

VERBOSE=0
while getopts ':v' opt; do
  case "$opt" in
    v) VERBOSE=1 ;;
    \?) echo "Unknown option -$OPTARG" >&2; exit 1 ;;
  esac
done
shift $((OPTIND - 1))   # removes -v and the '--' separator

echo "Verbose: $VERBOSE"
echo "Files to process:"
for f in "$@"; do
  echo "  -> $f"
done

Omslut getopts i en biblioteksfunktion

I modulära skript kan ni kapsla in getopts i en parse_args()-funktion som anger globala variabler (eller namngivningsreferenser). Då hålls main() ren och tolkningsfunktionen kan läsas in från andra skript.

Viktiga regler för det här mönstret:

  • Deklarera flaggvariablerna innan funktionen anropas
  • Använd global-variabler eller skicka värden via namngivningsreferenser (declare -n)
  • Returnera en avslutningskod som inte är noll vid felaktig indata, så att main kan reagera
#!/usr/bin/env bash

# Global option variables
VERBOSE=0; OUTPUT=''; COUNT=1

parse_args() {
  local opt
  while getopts ':vn:o:h' opt; do
    case "$opt" in
      v) VERBOSE=1 ;;
      n) COUNT="$OPTARG" ;;
      o) OUTPUT="$OPTARG" ;;
      h) echo "Usage: $(basename "$0") [-v] [-n N] [-o FILE]"; exit 0 ;;
      :) echo "Error: -$OPTARG needs a value" >&2; return 1 ;;
      \?) echo "Error: unknown option -$OPTARG" >&2; return 1 ;;
    esac
  done
  shift $((OPTIND - 1))
  ARGS=("$@")   # leftover positional args stored in array
}

main() {
  parse_args "$@" || exit 1
  echo "verbose=$VERBOSE count=$COUNT output=${OUTPUT:--} args=${ARGS[*]}"
}

main "$@"

Ett komplett verkligt exempel: en loggarkiverare

Här är ett komplett, verklighetsnära skript som använder allt som behandlats i den här lektionen: optstring med obligatoriska argument, tyst felläge, en usage-funktion, standardvärden, validering och OPTIND-skiftning.

Studera strukturen — den är mallen ni bör följa i varje skript ni skriver som behöver ett CLI-gränssnitt.

#!/usr/bin/env bash
# archive_logs.sh — compress and move logs older than N days

set -euo pipefail

DESTDIR='/tmp/log_archive'
DAYS=30
VERBOSE=0

usage() {
  cat >&2 <<EOF
Usage: $(basename "$0") [-v] [-d DAYS] [-o DIR] SOURCE_DIR

  -d DAYS   Archive logs older than DAYS (default: 30)
  -o DIR    Destination directory (default: /tmp/log_archive)
  -v        Verbose output
  -h        Show this help
EOF
  exit "${1:-0}"
}

while getopts ':d:o:vh' opt; do
  case "$opt" in
    d) DAYS="$OPTARG" ;;
    o) DESTDIR="$OPTARG" ;;
    v) VERBOSE=1 ;;
    h) usage 0 ;;
    :) echo "Error: -$OPTARG requires a value" >&2; usage 1 ;;
    \?) echo "Error: unknown option -$OPTARG" >&2; usage 1 ;;
  esac
done
shift $((OPTIND - 1))

# Validation
[[ $# -lt 1 ]] && { echo "Error: SOURCE_DIR is required" >&2; usage 1; }
[[ "$DAYS" =~ ^[0-9]+$ ]] || { echo "Error: DAYS must be numeric" >&2; exit 1; }
SOURCE="$1"
[[ -d "$SOURCE" ]] || { echo "Error: '$SOURCE' is not a directory" >&2; exit 1; }

mkdir -p "$DESTDIR"
[[ $VERBOSE -eq 1 ]] && echo "Archiving logs older than $DAYS days from $SOURCE to $DESTDIR"

find "$SOURCE" -name '*.log' -mtime "+$DAYS" -print | while read -r f; do
  gzip -c "$f" > "$DESTDIR/$(basename "$f").gz"
  [[ $VERBOSE -eq 1 ]] && echo "  archived: $f"
done

echo "Done."

Snabbkontroll: getopts optstring

Läs följande getopts-anrop och välj den korrekta beskrivningen av dess beteende:

while getopts ':f:vq' opt; do

Lektionssammanfattning: behärska getopts

Ni har lärt er att bygga professionella kommandoradsgränssnitt i Bash med getopts. Här är en sammanfattning av de viktigaste punkterna:

  • Optstring-syntax — bokstäver utan kolon är booleska flaggor; ett kolon efter en bokstav betyder att den kräver ett argument; ett inledande kolon aktiverar tyst felläge.
  • OPTARG — innehåller automatiskt argumentets värde för flaggor som kräver ett argument.
  • OPTIND — använd shift $((OPTIND - 1)) efter loopen för att göra återstående positionsparametrar tillgängliga i $@.
  • Tyst felläge — rekommenderas i produktion; hantera själv fallen : (saknat argument) och \? (okänd flagga) för full kontroll.
  • usage()-funktion — skriv alltid en sådan; skriv till stderr, avsluta med 0 för -h och med 1 vid fel.
  • Kombinerade flaggor — getopts hanterar automatiskt -vq och -n5 utan extra kod.
  • Modulärt mönster — kapsla in getopts i en parse_args()-funktion för rena, återanvändbara skript.

När ni behärskar getopts kan ni förvandla era skript från verktyg för ett enda ändamål till tillförlitliga och användarvänliga CLI-program som följer Unix-konventionerna.

Gratis att börja

Lär dig DevOps-bootcamp med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
142
Lektioner
568

Vanliga frågor

Är lektionen ”Parsa flaggor och argument med getopts” gratis?

Ja – du kan läsa vilka 3 lektioner som helst i lärvägen DevOps-bootcamp, inklusive ”Parsa flaggor och argument med getopts”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i DevOps-bootcamp innehåller totalt 4 lektioner.

Vad lär jag mig i ”Parsa flaggor och argument med getopts”?

Implementera professionella kommandoradsgränssnitt med getopts för korta alternativ, obligatoriska argument och användningsmeddelanden. Ni övar på DevOps-bootcamp med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig DevOps-bootcamp?

Du behöver inga förkunskaper. Utbildningen i DevOps-bootcamp på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 3 av 4.

Hur lång tid tar lektionen ”Parsa flaggor och argument med getopts”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här DevOps-bootcamp-lektionen?

Ja. Varje DevOps-bootcamp-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Utforma funktioner med lokal omfattning och returkoder
  2. Bygga och läsa in återanvändbara Bash-bibliotek
  3. Parsa flaggor och argument med getopts
  4. Skicka arrayer och associativa mappar mellan funktioner
← Tillbaka till DevOps-bootcamp