Гид по технологиям

Полное руководство по парсингу опций в Bash с помощью getopts

9 min read Shell scripting Обновлено 15 Dec 2025
Разбор getopts в Bash — полное руководство
Разбор getopts в Bash — полное руководство

Ноутбук на синем фоне с командной строкой Linux.

Основная цель статьи

Эта статья объясняет, как и почему использовать getopts в Bash-скриптах: от простых флагов до опций с аргументами, смешивания опций и позиционных параметров, а также частых ошибок и практических приёмов. Приведены готовые шаблоны, чеклисты для разработчика и методика тестирования.

Смысл и варианты поискового запроса

Primary intent: разбор getopts в Bash Related variants: парсинг опций bash, getopts пример, OPTARG OPTIND, обработка аргументов скрипта, разница getopts getopt


Введение: зачем нужен парсер опций

Когда вы вызываете скрипт, параметры передаются как $1, $2 и т.д. Но большинство утилит и сценариев используют опции (флаги) — короткие метки, которые начинаются с дефиса (-a, -l и т. п.). Если пользователь может передать опции в любом порядке, комбинировать их и указывать аргументы опций, ручной анализ $1, $2 становится быстро неудобным и хрупким. getopts упрощает эту задачу, оставаясь встроенным в Bash (не требует внешних утилит).

Краткое определение: getopts — встроенная команда Bash для последовательного чтения коротких опций и их аргументов из списка параметров команды.

Важно: getopts работает с односимвольными (короткими) опциями и не поддерживает длинные опции вида –long (см. раздел «Альтернативы»).


Когда getopts хорошо работает (и когда — нет)

Важно

  • Хорошо: компактные утилиты и скрипты, POSIX-совместимость, корректная обработка пробелов и кавычек, комбинирование флагов (-abc).
  • Плохо: длинные опции (–long), опциональные аргументы опции (getopts не поддерживает опциональные значения), сложные требования к нормализации порядка аргументов.

Контрпример: если вам нужны GNU-подобные длинные опции с автоматической перестановкой опций и их аргументов, лучше смотреть в сторону getopt (с осторожностью — разные реализации) или в сторону языковых парсеров (Python argparse).


Быстрый разбор синтаксиса getopts

Ключевые переменные и поведение:

  • Сигнатура: getopts optstring name
    • optstring — строка символов, задающая допустимые опции; двоеточие после буквы означает, что опция принимает аргумент (например, “b:”). Если первая буква optstring — двоеточие, shell-ошибки подавляются и поведение ошибок меняется.
    • name — имя переменной, в которую getopts поместит обнаруженную опцию.
  • OPTARG — содержит аргумент опции (если он предусмотрен).
  • OPTIND — индекс следующего параметра для обработки (число, счёт начинается с 1). После завершения разбора OPTIND указывает на позицию первого нераспознанного аргумента.

Основная схема использования:

while getopts ':ab:c' OPTION; do
  case "$OPTION" in
    a)  # обработка опции -a ;;
    b) argB="$OPTARG" ;;
    c)  # опция -c ;;
    ?)  echo "Usage: $(basename $0) [-a] [-b arg] [-c]"; exit 1 ;;
  esac
done

Подробности:

  • Комбинированные опции: если optstring = “abc”, вызов -ab будет разобран как -a и -b.
  • Если optstring включает двоеточие после буквы (например, “b:”), -b value или -bvalue дают значение в OPTARG.
  • Если передать неизвестную опцию, getopts вернёт ? (или : при первой двоеточии в optstring) и OPTARG будет содержать символ ошибки в соответствии с режимом.

Пример: простой разбор флагов

Сохраните как options.sh и сделайте исполняемым (chmod +x options.sh):

#!/bin/bash

while getopts 'abc' OPTION; do
  case "$OPTION" in
    a) echo "Option a used" ;;
    b) echo "Option b used" ;;
    c) echo "Option c used" ;;
    ?) echo "Usage: $(basename $0) [-a] [-b] [-c]"; exit 1 ;;
  esac
done

Тесты:

  • ./options.sh -a
  • ./options.sh -ab
  • ./options.sh -cab

Убедитесь, что порядок опций не важен: getopts обрабатывает каждую опцию последовательно.


Подавление сообщений оболочки и режим обработки ошибок

Если вы хотите подавить стандартные сообщения об ошибке от шелла (например, когда пользователь ввёл неизвестную опцию), поставьте двоеточие в начало optstring: ':abc'. В этом режиме getopts вернёт ? или : в переменную OPTION, и вы можете реализовать собственную логику сообщений.

Пример:

while getopts ':abc' OPTION; do
  case "$OPTION" in
    ?) echo "Usage: $(basename $0) [-a] [-b] [-c]"; exit 1 ;;
  esac
done

Поведение:

  • Если неизвестная опция и первый символ optstring не двоеточие, Bash печатает диагностическое сообщение.
  • Если первый символ optstring — двоеточие, диагностическое сообщение печататься не будет, и вы получите возможность сформировать своё сообщение об ошибке.

Опции с аргументами и OPTARG

Чтобы указать, что опция принимает аргумент, добавьте двоеточие сразу после буквы в optstring: b: означает, что -b требует аргумент.

Пример скрипта arguments.sh:

#!/bin/bash

while getopts ':ab:c:' OPTION; do
  case "$OPTION" in
    a) echo "Option a used" ;;
    b) argB="$OPTARG"; echo "Option b used with: $argB" ;;
    c) argC="$OPTARG"; echo "Option c used with: $argC" ;;
    ?) echo "Usage: $(basename $0) [-a] [-b argument] [-c argument]"; exit 1 ;;
  esac
done

Вызовы:

  • ./arguments.sh -a -b "how to geek" -c reviewgeek
  • ./arguments.sh -c reviewgeek -a

OPTARG содержит текст аргумента (без кавычек) — скопируйте его в переменную, если он нужен позже.

Примечание: getopts не поддерживает опциональные аргументы для конкретной опции (например, когда аргумент может быть либо отсутствовать, либо указан без специальных маркеров). Обычно это обходится разделением логики на отдельные опции или проверкой следующего параметра вручную.


Как отделить опции от обычных параметров: OPTIND + shift

Проблема: после разбора опций позиционные параметры $1, $2 могут содержать опции и их аргументы. Решение: используйте OPTIND, чтобы узнать индекс первого нераспознанного аргумента, затем выполните shift $((OPTIND - 1)).

Пример arguments3.sh:

#!/bin/bash

while getopts ':ab:c:' OPTION; do
  case "$OPTION" in
    a) echo "Option a used" ;;
    b) argB="$OPTARG"; echo "Option b used with: $argB" ;;
    c) argC="$OPTARG"; echo "Option c used with: $argC" ;;
    ?) echo "Usage: $(basename $0) [-a] [-b argument] [-c argument]"; exit 1 ;;
  esac
done

echo "Before - variable one is: $1"

shift "$((OPTIND - 1))"

echo "After - variable one is: $1"

echo "The rest of the arguments (operands)"
for x in "$@"; do
  echo "$x"
done

Запустите:

./arguments3.sh -a -c how-to-geek "dave dee" dozy beaky mick tich

Результат: до shift $1 содержал первый элемент из списка опций; после shift $1 указывает на первый не-опционный параметр (операнд).


Частые ошибки и как их избежать

Important

  • Неправильное расположение двоеточия в optstring. Первая двоеточие меняет поведение ошибок; двоеточие после буквы указывает на аргумент для конкретной опции.
  • Ожидание длинных опций: getopts не поддерживает --long. Если нужно — используйте ручной парсинг или внешние библиотеки.
  • Забыт shift: не выполняя shift после разбора, вы будете работать со смешанными параметрами (опции попадут в $1 и т.д.).
  • Неправильная обработка пустых или пробельных аргументов: всегда берите аргументы в кавычки, когда используете их (“$OPTARG”, “$@”, “$1”).

Практические шаблоны и приёмы (cheat sheet)

Шаблон минимального скрипта с опцией -h для помощи:

#!/bin/bash

usage() {
  cat <

Советы:

  • Всегда обрабатывайте -h/–help (getopts не поддерживает –help; можно предусмотреть ручную обработку аргумента –help до запуска getopts).
  • Записывайте аргументы опций в переменные (argB=”$OPTARG”), не используйте OPTARG в разных местах без копирования.
  • Для логирования используйте функцию debug(), которая учитывает значение verbose.

Альтернативы и когда их применять

  1. getopt (внешняя утилита)
  • Поддерживает длинные опции (GNU getopt), но поведение отличается на разных системах (BSD vs GNU). Требует осторожности и проверки транспортируемости.
  1. Ручной парсинг на основе цикла и case
  • Полный контроль, но код громоздкий и подвержен ошибкам при кавычках и пробелах.
  1. Использование языков-обёрток: Python argparse, Ruby OptionParser
  • Удобно для сложных CLI, с длинными опциями, подкомандами и автомагической генерацией помощи.

Выбор:

  • Простые инструменты и POSIX-совместимость: getopts.
  • Нужны длинные опции или богатая функциональность CLI: Python/Ruby или GNU getopt (с тестированием).

Совместимость и миграция

Совместимость:

  • getopts — встроенная команда Bash и POSIX-совместимых оболочек; доступна в bash, ksh, zsh (в прозрачном режиме), dash в ограничённой форме.
  • Поведение OPTIND/OPTARG одинаково в основных реализациях, но тестируйте на целевых системах.

Миграция с getopt:

  • Если вы хотите перейти с getopt на getopts, уберите поддержку длинных опций или добавьте доп. предобработчик: трансформируйте --long в -l до вызова getopts.

Совет по совместимости: при написании скриптов для разных дистрибутивов проверяйте shell на shebang (#!/bin/bash vs #!/bin/sh) и документируйте требования.


Тестирование и критерии приёмки

Минимальный набор тестов (unit/manual):

  • Тест: скрипт запускается без аргументов — ожидается поведение по умолчанию (exit 0 или помощь).
  • Тест: каждый флаг без аргумента должен выполнять соответствующее действие.
  • Тест: каждая опция с аргументом корректно передаёт значение в OPTARG/переменную.
  • Тест: комбинации флагов (-ab, -ba) дают эквивалентный результат.
  • Тест: неизвестные опции приводят к предсказуемой ошибке/выводу помощи.
  • Тест: смешивание опций и операндов, порядок: после shift операнды доступны в $1 и т.д.

Критерии приёмки:

  • Скрипт корректно разбирает все заданные опции и их аргументы во всех заявленных комбинациях.
  • Скрипт не выводит системных диагностик (если это нежелательно) и управляет ошибками через собственный механизм.
  • Документация (usage) актуальна и тесты проходят в целевой среде.

Роль-based чеклисты

Для разработчика:

  • Добавить обработку -h/–help (при необходимости) и демонстрационный usage.
  • Прописать optstring и проверить двоеточия.
  • Скопировать OPTARG в локальную переменную.
  • Использовать shift “$((OPTIND - 1))” после while.
  • Написать автоматические тесты (скрипты-обёртки).

Для тестировщика/DevOps:

  • Запустить скрипт на целевых хостах (Debian, RHEL, Alpine).
  • Проверить поведение при неизвестных опциях.
  • Проверить взаимодействие с crontab/Service при отсутствии tty.

Отладка и план действий при инциденте

Incident runbook (короткий):

  1. Воспроизведите вызов, который привёл к ошибке, с включённым set -x.
  2. Проверьте значение OPTIND и OPTARG на каждом шаге (вставьте debug-echo).
  3. Убедитесь, что optstring совпадает с ожиданиями (нет лишних/отсутствующих двоеточий).
  4. Если возникают системные сообщения shell, проверьте, не нужно ли добавить начальное ‘:’ в optstring.
  5. Протестируйте тот же сценарий в чистой оболочке (bash –noprofile –norc).

Ментальные модели и эвристики

Ментальная модель: думайте о getopts как о «ручном сканере» последовательности параметров: он читает по одному «токену» (опция или опция+аргумент), отдаёт результат, и вы решаете, что с ним делать.

Эвристики:

  • Всегда сохраняйте OPTARG в локальной переменной, если хотите её использовать позже.
  • Если ожидаете длинные опции — рассмотрите предобработчик, который преобразует --long=value в -l value.
  • Если ваш скрипт должен быть максимально переносимым, указывайте в shebang именно bash (#!/bin/bash) и документируйте требование.

Шаблоны и готовые сниппеты

  1. Обработка разделителя -- (явный конец опций): getopts сам корректно учитывает -- — когда встречается --, дальнейшие параметры считаются позиционными.

  2. Преобразование длинных опций простым предобработчиком (пример):

# Простая трансформация --output=val -> -o val
for arg in "$@"; do
  case $arg in
    --output=*) set -- "$@" "-o" "${arg#--output=}"; shift ;;
    --output) set -- "$@" "-o"; shift ;;
    *) set -- "$@" "$arg"; shift ;;
  esac
done
# Теперь можно запускать getopts на изменённом $@
  1. Запись логики verbose/debug:
log() { [ "$verbose" -eq 1 ] && echo "[DEBUG] $*"; }

Совместимость для русскоязычных окружений и локальные подводные камни

Локальные подсказки:

  • В скриптах, которые будут запускаться в разных локалях, будьте осторожны с локалями, если парсите строки, зависящие от локали (напр., сортировка). getopts сам локаль-нейтрален.
  • Для российского окружения обычно достаточно Bash из пакета bash (Debian/Ubuntu, CentOS/RHEL). На Alpine используется ash (BusyBox), где поддержка getopts присутствует, но проверьте нюансы поведения.

Безопасность и обработка неблагонадежных данных

Security notes:

  • Всегда экранируйте и бережно используйте значения OPTARG (например, не подставляйте их напрямую в eval или команды без проверки).
  • При приёме путей/имён файлов проверяйте их на неожиданные символы, если затем будете выполнять команды с интерполяцией.
  • Не доверяйте внешним данным — выполняйте валидацию аргументов (существование файла, допустимые значения, шаблоны).

Decision flow (Mermaid) — общий поток парсинга

flowchart TD
  A[Start] --> B{Есть аргументы?}
  B -- Да --> C[getopts извлекает следующую опцию]
  C --> D{Опция известна?}
  D -- Да --> E{Опция требует аргумент?}
  E -- Да --> F[OPTARG = аргумент]
  E -- Нет --> G[Устанавливаем флаг переменной]
  F --> H[Действие по опции]
  G --> H
  D -- Нет --> I{optstring начинается с ':'?}
  I -- Да --> J[Вернуть ':' или '?' и обработать собственно]
  I -- Нет --> K[Shell выведет ошибку]
  H --> B
  B -- Нет --> L[shift $''OPTIND - 1'' и дальше — позиционные параметры]
  L --> M[Script continues]

---

## Примеры ошибок и их исправления

1) Симптом: при вызове `./script.sh -a file1` $1 == "-a" вместо "file1".
   Исправление: убедитесь, что вызван shift "$((OPTIND - 1))" после цикла getopts.

2) Симптом: при неизвестной опции отображается сообщение от оболочки и ваш own usage тоже.
   Исправление: добавьте ':' в начало optstring и реализуйте собственную обработку ошибок.

3) Симптом: опция с аргументом получает следующий опцион как значение.
   Исправление: убедитесь, что аргумент передан верно и не начинается с дефиса, или обрабатывайте такие случаи вручную.

---

## Краткая сводка по командам и переменным

Fact box:
- getopts: встроенная команда Bash для разбора коротких опций.
- OPTARG: значение аргумента опции.
- OPTIND: индекс следующего параметра; используйте shift "$((OPTIND - 1))" чтобы очистить опции.
- optstring: строка, определяющая допустимые опции; двоеточие после буквы означает обязательный аргумент, двоеточие в начале — подавление системных сообщений об ошибках.

---

## Краткое резюме

- Используйте getopts для устойчивого парсинга коротких опций в Bash.
- Помните про OPTARG и OPTIND и всегда выполняйте shift после разбора опций.
- Для длинных опций и более сложных CLI используйте внешние инструменты или языковые библиотеки.

### Ключевые выводы
- getopts — простой и переносимый инструмент для коротких опций.
- Правильное расположение двоеточий в optstring критично.
- После обработки опций используйте shift для доступа к позиционным параметрам.

---

![Запуск скрипта с тремя словами как параметры.](/files/f6741f32-44c1-4778-be3d-2f6dc0b76ace.png)

![Передача четырёх параметров в скрипт, рассчитанный только на три.](/files/f787281e-3a07-40fd-82be-a0efd0b91737.png)

![Кавычки объединяют два параметра командной строки в один.](/files/33c50625-64d2-4608-819c-6ec5e26e67e9.png)

![Тестирование скрипта, принимающего переключатели командной строки.](/files/383bcda7-64ad-4fc4-839c-ccdeaa6c69e0.png)

---

Короткое объявление (announcement):
Если вы автоматизируете задачи в Bash, getopts — обязательная штука в арсенале. Оно даёт предсказуемый и переносимый способ обработки коротких опций, позволяя вашим скриптам вести себя как настоящие POSIX-утилиты.
Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

RDP: полный гид по настройке и безопасности
Инфраструктура

RDP: полный гид по настройке и безопасности

Android как клавиатура и трекпад для Windows
Гайды

Android как клавиатура и трекпад для Windows

Советы и приёмы для работы с PDF
Документы

Советы и приёмы для работы с PDF

Calibration в Lightroom Classic: как и когда использовать
Фото

Calibration в Lightroom Classic: как и когда использовать

Отключить Siri Suggestions на iPhone
iOS

Отключить Siri Suggestions на iPhone

Рисование таблиц в Microsoft Word — руководство
Office

Рисование таблиц в Microsoft Word — руководство