0Pricing
DevOps Bootcamp · Lekcja

Analizowanie flag i argumentów za pomocą getopts

Implementuj profesjonalne interfejsy wiersza poleceń za pomocą getopts dla krótkich opcji, wymaganych argumentów i komunikatów użycia.

Analizowanie flag i argumentów za pomocą getopts to bezpłatna lekcja DevOps Bootcamp na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej DevOps Bootcamp, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs DevOps Bootcamp zawiera 4 lekcji w sumie.

Dlaczego istnieje getopts

Każdy praktyczny skrypt prędzej czy później musi przyjmować opcje takie jak -v, -o output.txt czy -n 5. Ręczne ich analizowanie za pomocą $1, $2… szybko staje się kruche.

getopts to wbudowane narzędzie zgodne ze standardem POSIX, które niezawodnie obsługuje krótkie opcje (-a, -b), w tym opcje przyjmujące argument. Jest dostępne w każdej powłoce POSIX, więc nie są wymagane żadne zależności.

  • Obsługuje połączone flagi: -vn 5 = -v -n 5
  • Elegancko zgłasza nieznane opcje
  • Automatycznie ustawia standardowe zmienne OPTIND i OPTARG

W tej lekcji zbudują Państwo od podstaw kompletny, profesjonalny interfejs CLI za pomocą getopts.

Składnia getopts

Podstawowa składnia to pętla while, która przy każdej iteracji wywołuje getopts:

while getopts "optstring" varname; do
  case "$varname" in
    ...
  esac
done
  • optstring — ciąg zawierający litery wszystkich akceptowanych opcji. Dwukropek po literze oznacza, że dana opcja wymaga argumentu.
  • varname — przy każdej iteracji otrzymuje literę bieżącej opcji.
  • OPTARG — automatycznie otrzymuje wartość argumentu, gdy po literze znajduje się dwukropek.
  • OPTIND — indeks następnego argumentu do przetworzenia; po zakończeniu pętli należy wykonać shift $((OPTIND - 1)), aby udostępnić pozostałe parametry pozycyjne.
#!/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

Definiowanie optstring

optstring to zwięzła deklaracja kontraktu interfejsu CLI. Każdy znak reprezentuje jedną akceptowaną flagę.

  • 'abc' — akceptuje -a, -b, -c (bez argumentów)
  • 'a:bc' — opcja -a wymaga argumentu; -b i -c go nie wymagają
  • ':abc' — początkowy dwukropek włącza tryb cichej obsługi błędów (skrypt obsługuje nieprawidłowe opcje, zamiast wyświetlania komunikatu przez powłokę)

Tryb cichy jest preferowany w skryptach produkcyjnych, ponieważ zapewnia pełną kontrolę nad komunikatami błędów i kodami zakończenia.

#!/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 i wymagane argumenty

Gdy po fladze w optstring znajduje się dwukropek, getopts zapisuje jej wartość w OPTARG. Użytkownik może podać argument ze spacją lub bez niej:

  • -o report.txt
  • -oreport.txt

Obie formy są analizowane identycznie. To jedna z kluczowych zalet w porównaniu z ręcznym analizowaniem za pomocą $1/shift.

W trybie cichym (gdy ':' znajduje się na początku optstring) brak argumentu powoduje ustawienie przez getopts wartości : w zmiennej varname oraz litery opcji w OPTARG — jest to idealne rozwiązanie do przygotowania precyzyjnego komunikatu błędu.

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

Przesuwanie za opcje za pomocą OPTIND

Po zakończeniu działania getopts zmienna OPTIND zawiera indeks pierwszego argumentu niebędącego opcją. Należy użyć shift, aby usunąć wszystkie przetworzone opcje, dzięki czemu $1, $2… będą odnosić się do pozostałych parametrów pozycyjnych (na przykład nazw plików).

Idiom zawsze wygląda tak:

shift $((OPTIND - 1))

Po przesunięciu $@ zawiera wyłącznie argumenty, które nie były flagami — operandy polecenia.

#!/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: $*"

Pisanie funkcji usage

Profesjonalny skrypt zawsze udostępnia funkcję usage(), która wyświetla komunikat pomocy i kończy działanie. Przyjęta konwencja to:

  • Wyświetlać komunikat na stderr (deskryptor 2), aby nie zanieczyszczał danych przekazywanych potokiem
  • Kończyć działanie kodem 0 dla -h / --help oraz kodem 1 w przypadku nieprawidłowego użycia
  • Wywoływać usage 1 w ścieżkach obsługi błędów i usage 0 w obsłudze -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:--}"

Wartości domyślne i weryfikacja

Po przeanalizowaniu argumentów należy zweryfikować dane i ustawić wartości domyślne, zanim skrypt wykona właściwą pracę. Faza analizy (pętla) powinna być oddzielona od fazy logiki. Dzięki temu obie sekcje są łatwiejsze do czytania i testowania.

  • Używać ${VAR:-default} do definiowania wartości domyślnych w miejscu użycia
  • Weryfikować argumenty liczbowe za pomocą wyrażenia regularnego lub kontroli arytmetycznej
  • Sprawdzać, czy wymagane opcje zostały rzeczywiście podane
#!/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

Łączenie flag w wierszu poleceń

getopts automatycznie obsługuje połączone krótkie flagi zapisywane bez spacji, zgodnie ze standardową konwencją Uniksa:

  • -v -q jest równoważne z -vq
  • -n 5 -v jest równoważne z -n5 -v lub -vn5

Nie trzeba pisać dodatkowego kodu, aby to obsłużyć — getopts automatycznie przechodzi przez każdy znak połączonego ciągu opcji. To kolejny ważny powód, aby używać getopts zamiast ręcznego analizowania.

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

Obsługa separatora podwójnego myślnika

Polecenia uniksowe akceptują -- (podwójny myślnik) jako jawny sygnał zakończenia przetwarzania opcji. Wszystko po -- jest traktowane jako argument pozycyjny, nawet jeśli wygląda jak flaga.

getopts automatycznie kończy działanie po napotkaniu --. Po wykonaniu shift $((OPTIND - 1)) podwójny myślnik znika, a $@ zawiera wyłącznie operandy.

Jest to ważne w skryptach operujących na nazwach plików, które mogą zaczynać się od myślnika, na przykład:

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

Opakowywanie getopts w funkcję biblioteczną

W skryptach modułowych można zamknąć getopts w funkcji parse_args(), która ustawia zmienne globalne (lub zmienne typu nameref). Dzięki temu main() pozostaje przejrzysta, a parser można ładować w innych skryptach.

Najważniejsze zasady tego wzorca:

  • Zadeklarować zmienne opcji przed wywołaniem funkcji
  • Używać zmiennych global albo przekazywać wartości za pomocą nameref (declare -n)
  • Zwracać niezerowy kod zakończenia w przypadku nieprawidłowych danych, aby funkcja main mogła zareagować
#!/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 "$@"

Kompletny praktyczny przykład: archiwizator logów

Oto kompletny, praktyczny skrypt wykorzystujący wszystkie elementy omówione w tej lekcji: optstring z wymaganymi argumentami, tryb cichej obsługi błędów, funkcję usage, wartości domyślne, weryfikację oraz przesunięcie OPTIND.

Proszę przeanalizować jego strukturę — jest to szablon, którego należy używać w każdym pisanym skrypcie wymagającym interfejsu CLI.

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

Szybkie sprawdzenie: optstring getopts

Proszę przeczytać poniższe wywołanie getopts i wybrać poprawny opis jego działania:

while getopts ':f:vq' opt; do

Podsumowanie lekcji: biegłość w getopts

Dowiedzieli się Państwo, jak tworzyć profesjonalne interfejsy wiersza poleceń w Bashu za pomocą getopts. Oto podsumowanie najważniejszych informacji:

  • Składnia optstring — litery bez dwukropka oznaczają flagi logiczne; dwukropek po literze oznacza, że opcja wymaga argumentu; początkowy dwukropek włącza tryb cichej obsługi błędów.
  • OPTARG — automatycznie przechowuje wartość argumentu dla opcji, które go wymagają.
  • OPTIND — po zakończeniu pętli należy użyć shift $((OPTIND - 1)), aby udostępnić pozostałe parametry pozycyjne w $@.
  • Tryb cichej obsługi błędów — preferowany w środowisku produkcyjnym; należy samodzielnie obsłużyć przypadki : (brak argumentu) i \? (nieznana opcja), aby uzyskać pełną kontrolę.
  • Funkcja usage() — należy zawsze ją pisać; komunikat wyświetlać na stderr, kończyć działanie kodem 0 dla -h i kodem 1 w przypadku błędów.
  • Połączone flagi — getopts automatycznie obsługuje -vq i -n5, bez dodatkowego kodu.
  • Wzorzec modułowy — należy opakować getopts w funkcję parse_args(), aby uzyskać przejrzyste skrypty wielokrotnego użytku.

Opanowanie getopts zmienia skrypty z narzędzi jednego zastosowania w niezawodne i przyjazne użytkownikowi programy CLI, zgodne z konwencjami Uniksa.

Często zadawane pytania

Czy lekcja „Analizowanie flag i argumentów za pomocą getopts” jest bezpłatna?

Tak — pełny tekst „Analizowanie flag i argumentów za pomocą getopts” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu DevOps Bootcamp, przejdź na CoddyKit PRO. Kurs DevOps Bootcamp zawiera 4 lekcji w sumie.

Co nauczysz się w „Analizowanie flag i argumentów za pomocą getopts”?

Implementuj profesjonalne interfejsy wiersza poleceń za pomocą getopts dla krótkich opcji, wymaganych argumentów i komunikatów użycia. Ćwiczysz DevOps Bootcamp z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć DevOps Bootcamp?

Nie wymagamy żadnego doświadczenia. DevOps Bootcamp w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.

Ile czasu zajmuje lekcja „Analizowanie flag i argumentów za pomocą getopts”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji DevOps Bootcamp?

Tak. Każda lekcja DevOps Bootcamp zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Projektowanie funkcji z zakresem lokalnym i kodami zwrotnymi
  2. Budowanie i dołączanie wielokrotnego użytku bibliotek Bash
  3. Analizowanie flag i argumentów za pomocą getopts
  4. Przekazywanie tablic i map asocjacyjnych między funkcjami
← Powrót do DevOps Bootcamp