НейроАгент

Полное руководство: парсинг аргументов командной строки в Bash

Освойте парсинг аргументов командной строки в скриптах Bash с помощью getopts и getopt. Научитесь обрабатывать комбинированные флаги (-vfd) и отдельные флаги (-v -f -d) с практическими примерами и лучшими практиками для надежного shell-скриптинга.

Вопрос

Как разобрать аргументы командной строки в Bash-скриптах?

Мне нужно обрабатывать разные форматы аргументов в моем Bash-скрипте:

Пример 1:

bash
./myscript -vfd ./foo/bar/someFile -o /fizz/someOtherFile

Пример 2:

bash
./myscript -v -f -d -o /fizz/someOtherFile ./foo/bar/someFile

Какой принятый способ разбора этих аргументов командной строки, чтобы:

  • переменные $v, $f и $d устанавливались в true при наличии соответствующих флагов
  • переменная $outFile равнялась /fizz/someOtherFile при наличии флага -o

Мне нужно решение, которое работает с обоими форматами аргументов и любой комбинацией флагов.

НейроАгент

Разбор аргументов командной строки в Bash скриптах

Для разбора аргументов командной строки в скриптах Bash можно использовать встроенную команду getopts для простых случаев или внешнюю утилиту getopt для более сложных сценариев. Оба подхода позволяют обрабатывать различные форматы аргументов, включая короткие опции (-vfd) и отдельные опции (-v -f -d), а также правильно захватывать значения опций.

Содержание


Использование getopts для простого разбора аргументов

getopts - это встроенная команда Bash, которая предоставляет простой способ разбора опций командной строки. Идеально подходит для скриптов с простыми требованиями к опциям.

Базовый синтаксис

Синтаксис getopts имеет следующий вид:

bash
while getopts "option_string" opt_name; do
    case $opt_name in
        option) handle_option ;;
        *) handle_unknown ;;
    esac
done

Пример реализации

Вот как реализовать getopts для ваших конкретных требований:

bash
#!/bin/bash

# Инициализация переменных
v=false
f=false
d=false
outFile=""

# Разбор опций
while getopts "vfd:o:" opt; do
    case $opt in
        v) v=true ;;
        f) f=true ;;
        d) d=true ;;
        o) outFile="$OPTARG" ;;
        \?) echo "Недопустимая опция: -$OPTARG" >&2; exit 1 ;;
        :) echo "Для опции -$OPTARG требуется аргумент." >&2; exit 1 ;;
    esac
done

# Сдвиг обработанных аргументов
shift $((OPTIND-1))

# Оставшиеся аргументы - позиционные параметры
inputFile="$1"

# Вывод результатов для проверки
echo "Режим подробного вывода: $v"
echo "Режим принудительного выполнения: $f"
echo "Режим отладки: $d"
echo "Выходной файл: $outFile"
echo "Входной файл: $inputFile"

Как это работает

  • getopts "vfd:o:" указывает допустимые опции:
    • v, f, d - это флаги-переключатели
    • o: требует аргумент (двоеточие указывает на это)
  • OPTARG содержит аргумент для опции, которая его требует
  • OPTIND указывает на следующий аргумент для обработки
  • Оператор case обрабатывает каждую опцию соответствующим образом

Использование getopt для продвинутого разбора аргументов

Хотя getopt не является встроенной командой Bash, он предоставляет более сложные возможности разбора аргументов.

Базовый синтаксис

bash
options=$(getopt -o "vfd:o:" -- "$@")
eval set -- "$options"
while true; do
    case "$1" in
        -v) v=true; shift ;;
        -f) f=true; shift ;;
        -d) d=true; shift ;;
        -o) outFile="$2"; shift 2 ;;
        --) shift; break ;;
        *) break ;;
    esac
done

Пример реализации

bash
#!/bin/bash

# Инициализация переменных
v=false
f=false
d=false
outFile=""

# Разбор опций с getopt
options=$(getopt -o "vfd:o:" -- "$@")
if [ $? -ne 0 ]; then
    echo "Ошибка разбора аргументов" >&2
    exit 1
fi

eval set -- "$options"
while true; do
    case "$1" in
        -v) v=true; shift ;;
        -f) f=true; shift ;;
        -d) d=true; shift ;;
        -o) outFile="$2"; shift 2 ;;
        --) shift; break ;;
        *) echo "Внутренняя ошибка!" >&2; exit 1 ;;
    esac
done

# Оставшиеся аргументы - позиционные параметры
inputFile="$1"

# Вывод результатов
echo "Режим подробного вывода: $v"
echo "Режим принудительного выполнения: $f"
echo "Режим отладки: $d"
echo "Выходной файл: $outFile"
echo "Входной файл: $inputFile"

Почему использовать getopt?

  • Обрабатывает более сложные форматы аргументов
  • Лучшее обработка ошибок
  • Поддержка длинных опций (–verbose, --force и т.д.)
  • Более надежная работа с смешанными типами аргументов

Полное примерное решение

Вот комплексный скрипт, который обрабатывает оба формата аргументов и любую комбинацию флагов:

bash
#!/bin/bash

# Инициализация переменных со значениями по умолчанию
v=false
f=false
d=false
outFile=""

# Функция для отображения справки
usage() {
    echo "Использование: $0 [-v] [-f] [-d] [-o output_file] input_file"
    echo "Опции:"
    echo "  -v          Включить режим подробного вывода"
    echo "  -f          Включить режим принудительного выполнения"
    echo "  -d          Включить режим отладки"
    echo "  -o file     Указать выходной файл"
    exit 1
}

# Разбор опций с использованием getopts (рекомендуется для большинства случаев)
while getopts "vfd:o:h" opt; do
    case $opt in
        v) v=true ;;
        f) f=true ;;
        d) d=true ;;
        o) outFile="$OPTARG" ;;
        h) usage ;;
        \?) echo "Недопустимая опция: -$OPTARG" >&2; usage ;;
        :) echo "Для опции -$OPTARG требуется аргумент." >&2; usage ;;
    esac
done

# Сдвиг обработанных аргументов
shift $((OPTIND-1))

# Проверка наличия требуемых аргументов
if [ $# -eq 0 ]; then
    echo "Ошибка: Требуется указать входной файл" >&2
    usage
fi

inputFile="$1"

# Проверка, указан ли выходной файл при необходимости
if [ -n "$outFile" ]; then
    echo "Выходной файл: $outFile"
else
    echo "Предупреждение: Выходной файл не указан"
fi

# Отображение всех настроек
echo "Настройки скрипта:"
echo "  Режим подробного вывода: $v"
echo "  Режим принудительного выполнения: $f"
echo "  Режим отладки: $d"
echo "  Входной файл: $inputFile"
echo "  Выходной файл: ${outFile:-'Не указан'}"

# Продолжение логики скрипта...

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

Сохраните это как myscript и сделайте его исполняемым:

bash
chmod +x myscript

Затем протестируйте его с обоими форматами:

bash
# Формат 1: Объединенные опции
./myscript -vfd ./foo/bar/someFile -o /fizz/someOtherFile

# Формат 2: Отдельные опции
./myscript -v -f -d -o /fizz/someOtherFile ./foo/bar/someFile

Оба варианта дадут одинаковый вывод:

Выходной файл: /fizz/someOtherFile
Настройки скрипта:
  Режим подробного вывода: true
  Режим принудительного выполнения: true
  Режим отладки: true
  Входной файл: ./foo/bar/someFile
  Выходной файл: /fizz/someOtherFile

Лучшие практики для разбора аргументов командной строки

1. Используйте getopts для простых скриптов

  • Встроен в Bash
  • Нет внешних зависимостей
  • Достаточно для большинства случаев использования

2. Предоставляйте четкую информацию об использовании

bash
usage() {
    echo "Использование: $0 [опции] input_file"
    echo "  -v          Режим подробного вывода"
    echo "  -f          Принудительное выполнение операции"
    echo "  -d          Режим отладки"
    echo "  -o file     Выходной файл"
    echo "  -h          Показать это справочное сообщение"
    exit 1
}

3. Корректно обрабатывайте ошибочные случаи

bash
if [ -z "$inputFile" ]; then
    echo "Ошибка: Требуется указать входной файл" >&2
    usage
fi

4. Используйте осмысленные имена переменных

bash
# Хорошо
use_verbose_mode=false
force_operation=false
debug_enabled=false

# Избегайте
v=false
f=false
d=false

5. Проверяйте аргументы опций

bash
if [ -n "$outFile" ] && [ ! -d "$(dirname "$outFile")" ]; then
    echo "Ошибка: Выходная директория не существует" >&2
    exit 1
fi

6. Поддерживайте длинные опции с getopt

Для более удобных для пользователя скриптов рассмотрите возможность добавления поддержки длинных опций:

bash
options=$(getopt -l "verbose,force,debug,output:" -o "vfd:o:h" -- "$@")

Сравнение: getopts vs getopt

Особенность getopts getopt
Доступность Встроен в Bash Внешняя команда (обычно устанавливается)
Длинные опции Не поддерживаются Поддерживаются с опцией -l
Обработка ошибок Базовая Более совершенная
Смешение аргументов Ограниченная Лучшая поддержка смешанных аргументов
Портативность Высокая (работает везде, где доступен Bash) Ниже (может не быть установлена на всех системах)
Сложность Просто в использовании Более сложная настройка
Рекомендация Для большинства скриптов Для сложных потребностей в разборе аргументов

Когда использовать что

Используйте getopts когда:

  • Ваш скрипт работает на минимальных системах
  • Вам нужны только короткие опции
  • Вы хотите избежать внешних зависимостей
  • Логика разбора проста

Используйте getopt когда:

  • Вам нужны длинные опции (–verbose, --force)
  • Вы хотите лучшую обработку ошибок
  • Вам нужно обрабатывать сложные шаблоны аргументов
  • Вы работаете на системах, где getopt гарантированно установлен

Заключение

  1. Для большинства скриптов Bash встроенная команда getopts предоставляет достаточную функциональность для разбора аргументов командной строки, поддерживая как объединенные, так и отдельные форматы опций.

  2. Начинайте с getopts из-за его простоты и широкого распространения, переходите к getopt только если вам нужны расширенные функции, такие как длинные опции или более совершенная обработка ошибок.

  3. Всегда включайте документацию по использованию, чтобы помочь пользователям понять, как правильно вызывать ваш скрипт с различными комбинациями аргументов.

  4. Проверяйте ваши аргументы, чтобы обеспечить надежную обработку ошибок и предотвратить непредвиденное поведение при передаче недопустимых опций или отсутствии требуемых аргументов.

  5. Тщательно тестируйте с разными форматами аргументов, чтобы убедиться, что ваш скрипт работает последовательно независимо от того, как пользователи выбирают указывать свои опции.

Предоставленное примерное решение обрабатывает оба указанных вами формата аргументов и устанавливает соответствующие переменные при наличии флагов или предоставлении опций. Вы можете расширить этот шаблон для соответствия дополнительным опциям и аргументам в соответствии с вашими конкретными потребностями использования.

Источники

  1. Руководство по Bash - Встроенная команда Shopt
  2. Расширенное руководство по Bash-скриптингу - Глава 33: Параметры
  3. Руководство getopt - Документация GNU Coreutils
  4. Stack Overflow - Как разобрать аргументы командной строки в Bash
  5. IBM Developer - Bash-скриптинг: Лучший getopts