колотите getopts, короткие опции только, все требуют значений, владеют проверкой

Да, Вы можете. Страницы справочника записаны как nroff файлы.
/usr/local/man каталог является местоположением, обычно используемым для любых локально установленных пакетов/файлов.
Можно посмотреть на примеры путем рассмотрения существующих страниц справочника, (который должен будет, вероятно, быть несжатым сначала), также считайте человека.
В настоящее время многие пользователи предпочитают groff nroff, man groff начать

8
09.05.2013, 14:03
5 ответов

Когда Вы называете свой второй сценарий (я сохранил его как getoptit) с:

getoptit -d -h

Это распечатает:

MYSQL_HOST=''  MYSQL_USER=''  MYSQL_PASS=''  BACKUP_DIR='-h' Additionals: 

Таким образом, BACKUP_DIR установлен, и Вы тестируете с if [ ! "$BACKUP_DIR" ]; then если это не установлено, таким образом, нормально, что код в нем не инициирован.

Если Вы хотите протестировать, если каждая опция установлена однажды, необходимо сделать это, прежде чем Вы сделаете присвоение от значения $OPTARG. И необходимо, вероятно, также проверить на $OPTARG для запуска с a '-' (для -d -h ошибка) перед присвоением:

...
            d)
                    if [ ! -z "$BACKUP_DIR" ]; then
                            echo "backup dir already set"
                            exit 2
                    fi
                    if [ z"${OPTARG:0:1}" == "z-" ]; then
                            echo "backup dir starts with option string"
                            exit 2
                    fi
                    BACKUP_DIR=$OPTARG
                    ;;
...
4
27.01.2020, 20:11
  • 1
    Превосходное объяснение. Имеет смысл, после того как я думал о том, что существует на самом деле a while цикл, работающий на основе опций. Это - метод, с которым я пошел как, хотя это является подробным по сравнению с другими, очень ясно, что продолжается в сценарии. И пригодность для обслуживания другими важна в этом случае. –  batfastad 15.05.2013, 16:46

Так как другие ответы на самом деле не отвечают на Ваш вопрос так: Это - ожидаемое поведение и на основе того, как POSIX интерпретируется:

Когда опция потребует аргумента опции, getopts утилита должна поместить ее в переменную оболочки OPTARG. Если никакая опция не была найдена, или если опция, которая была найдена, не будет иметь аргумента опции, то OPTARG должен быть сброшен.)

Это - все, что указывается, и помещать (не так долго) короткая история: getopts волшебно не знает, что совершенно допустимым аргументом, он видит опцию, которой Вы требуете, чтобы иметь аргумент, является на самом деле не аргумент опции, но другая опция. Ничто не препятствует тому, чтобы Вы имели -h как допустимый аргумент -d опция, которая в практике означает это getopts только бросит ошибку, если Ваша опция, которая требует аргумента, будет последней на командной строке, например:

test.sh:

#!/bin/sh

while getopts ":xy:" o; do
    case "${o}" in
        :) echo "${OPTARG} requires an argument"; exit 1;
    esac
done

Пример:

$ ./test.sh -y -x
$

$ ./test.sh -x -y
y requires an argument

Причина, почему Ваш второй подход не работает, состоит в том потому что парсинг это getopts делает все еще то же, поэтому после того как Вы в цикле, "ущерб" уже нанесен.

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

3
27.01.2020, 20:11

Я продолжил бы использовать getopts но сделайте некоторую дополнительную проверку после: (непротестированный)

errs=0
declare -A option=(
    [MYSQL_HOST]="-h"
    [MYSQL_USER]="-u"
    [MYSQL_PASS]="-p"
    [BACKUP_DIR]="-d" 
)
for var in "${!option[@]}"; do
    if [[ -z "${!var}" ]]; then
        echo "error: specify a value for $var with ${option[var]}"
        ((errs++))
    fi
done
((errs > 0)) && exit 1

требует версии 4 удара

2
27.01.2020, 20:11

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

Я нашел статью, выдерживающую сравнение getopts и getopt, который, вероятно, будет полезен, поскольку руководство довольно трудно понять (по крайней мере, перед кофе).

1
27.01.2020, 20:11

Во-первых, необходимо использовать if [ -z "$MYSQL_USER" ].

Во-вторых, нет никакой потребности в присвоении - if [ -z "$OPTARG" ] будет хорошо работать.

В-третьих, я подозреваю то, что Вы на самом деле хотите, if [ ${#OPTARG} = 0 ]. $ {#x} является возвратами вещи удара длина строкового $x (см. больше здесь).

В-четвертых, если бы Вы делаете свою собственную проверку, я рекомендовал бы getopt вместо getopts, поскольку это обеспечивает намного больше гибкости.

Наконец, для ответа на первый вопрос можно обнаружить, когда флаг передается как аргумент путем помещения списка флагов наверху, как это:

args=( -h -u -p -d )

И затем имея регистрацию опция, где Вы хотите проверить, является ли предоставленным аргументом опция, что-то вроде этого:

d)
    BACKUP_DIR=$OPTARG
    if [ "$(echo ${args[@]/$OPTARG/})" = "$(echo ${args[@]})" ]
    then
        echo "Argument is an option! Error!"
    fi

Не идеальный ответ, но это работает! Ваша проблема состоит в том, что "-h" является совершенно допустимым аргументом, и Вы уступаете дорогу не, чтобы оболочка знала, что это только ищет параметры, которые не являются также допустимыми флагами.

1
27.01.2020, 20:11

Теги

Похожие вопросы