Разбор аргументов командной строки --this = style в bash - PullRequest
0 голосов
/ 04 февраля 2020

Я бы хотел разобрать аргументы командной строки --this = style в bash.

Основные требования:

  • - abc = xyz Очевидно, следует установить ab c в xyz
  • - вещь должна установить вещь = истина
  • - вещь не должна установить вещь = ложь
  • Минимальный шум при определении значений по умолчанию.

Другие ограничения:

  • Полезно не использовать аргументы, не относящиеся к этому стилю,
  • Меня не интересует краткая форма -a -b - c style.
  • Было бы неплохо требовать определенных аргументов.

Меня интересуют оба коротких и легких переносных решения, которые можно просто встроить в любой скрипт, но и более крупные решения в стиле библиотеки, которые предоставляют больше возможностей. Ниже приведена середина базового решения, которое я приготовил (наихудший из обоих миров?), Но мне будет интересно посмотреть, какие другие идеи у людей есть, чтобы сбалансировать компромисс между длиной и функциональностью.

parse_args. sh

# Parse double dashed command line options.
#
# Parse positional options in the following formats:
#  --option         Sets {option} to "true".
#  --no-option      Sets {option} to "false".
#  --option=value   Sets {option} to {value}.
# 
# Option names must already be defined or an "unknown option" error will be
# printed to stderr.
#
# Output variables:
#   remaining_args  All remaining args in the order
#                   they were defined.
#
# Returns: 1 if there was an error.
parse_args() {
  remaining_args=() 
  for arg; do
    if [[ "$arg" =~ ^--(.+)$ ]]; then
      local k="${BASH_REMATCH[1]}"
      local v=true
      if [[ "$k" =~ ^([^=]+)=(.*)$ ]]; then
        k="${BASH_REMATCH[1]}"
        v="${BASH_REMATCH[2]}"
      elif [[ "$k" =~ ^no-(.*)$ ]]; then
        k="${BASH_REMATCH[1]}"
        v=false
      fi
      if [[ ! -v "$k" ]]; then
        echo "error: unknown option: '$k'" > /dev/stderr
        return 1
      fi
      eval $k="$v"
    else
      remaining_args+=("$arg")
    fi
  done 

  return 0
}

Вот пример программы, использующей его:

пример. sh

#!/bin/bash

. parse_args.sh

# Declare defaults
breakfast="avocado toast"
lunch="burrito"
vegetarian=false
vegan=true

# Define help as a string, not a function, so that we have access to the
# defaults
help=$( cat - <<EOF
Usage: $0 --option=value other_food1 ... other_foodN

Options (with given defaults):

  breakfast ($breakfast)
    What to eat for breakfast.

  lunch ($lunch)
    What to eat for lunch.

  vegetarian ($vegetarian)
    Whether the meals should be vegetarian or not.

  vegan ($vegan)
    Whether the meals should be vegan or not.

other_foodN:
  Positional arguments are other foods.  These can be before, after, or in
  between options.
EOF
)

parse_args "$@" || { echo "$help" > /dev/stderr; exit 1 ; }
set -- "${remaining_args[@]}"

cat - <<EOF
  breakfast: '$breakfast'
      lunch: '$lunch'
 vegetarian: '$vegetarian'
      vegan: '$vegan'
other foods:
EOF

for p; do echo "  '$p'" ; done

Запуск выглядит так:

$ ./example.sh \
  --breakfast=muesli mole \
  --lunch=rosti horchata \
  --vegetarian \
  --no-vegan

  breakfast: 'muesli'
      lunch: 'rosti'
 vegetarian: 'true'
      vegan: 'false'
other foods:
  'mole'
  'horchata'


Редактировать:

Пока копая немного больше, я обнаружил, что мой старый сотрудник в итоге портировал библиотеку "тяжеловесов" из моей старой работы. https://github.com/kward/shflags/blob/master/README.md Это именно то, что я хотел для «тяжеловесных» решений, спасибо Кейт за портирование! Мне все еще интересно видеть идеи, которые есть у людей для облегченных версий.

1 Ответ

1 голос
/ 04 февраля 2020

Я бы предложил использовать case

#!/bin/bash

while [[ $@ ]]; do
    case $1 in
        --abc=*   ) abc=${1/--abc=/};;
        --thing   ) thing=true ;;
        --no-thing) thing=false;;
        *         ) echo 'error'; exit 1;;
    esac
    shift
done

echo $abc $thing

И пример использования этого

$ ./test --abc='hello world!' --thing
hello world! true
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...