2014-01-06 5 views
3

Я знаю, как обращаться необязательные аргументы с помощью getopts в BashКак разрешить необязательные аргументы перед необязательными аргументами, используя getopts в Bash?

#!/bin/bash 

while getopts ":a:p:drh" opt; do 
    case "$opt" in 
    a) echo $OPTARG;; 
    esac 
done 

Но если мой сценарий ожидает ./script.sh arg1 [options], как я могу сказать getopts пропустить arg1?

$ ./script.sh -a 1234 
1234 
$ ./script.sh arg1 -a 1234 
$ ./script.sh arg1 
$ ./script.sh -a 1234 arg1 
1234 

Как я вижу, я могу обработать аргумент, если аргумент помещается в последнюю позицию. Какое «регулярное выражение» мне нужно в getopts, чтобы мой позиционный аргумент находился перед дополнительным аргументом?

Предложения от How to allow non-option arguments in any order to getopt?, похоже, переупорядочивают аргументы.

ответ

1

Если вы знаете, количество позиционных аргументов, то вы можете сделать что-то вроде этого:

#!/bin/bash 

VAR=$1 
shift 
echo $VAR 

while getopts ":a:p:drh" opt; do 
    case "$opt" in 
    a) echo $OPTARG;; 
    esac 
done 

Пример:

> ./test.sh mist -a 2345 -p 45 
mist 
2345 
+0

Спасибо. Это, наверное, единственный лучший, самый дешевый обходной путь! – CppLearner

3

Вот как я бы это сделать. У вас может быть множество необязательных аргументов, размещенных где угодно.

#!/bin/bash 

while [ $# -gt 0]; do 
    while getopts ":a:p:drh" opt; do 
    case "$opt" in 
     a) echo $OPTARG; shift;; 
     p) echo $OPTARG; shift;; 
     d) echo Option d;; 
     r) echo Option r;; 
     h) echo Option h;; 
     \?) echo unknown Option;; 
     :) echo missing required parameter for Option $OPT;; 
    esac 
    shift 
    OPTIND=1 
    done 
    if [ $# -gt 0 ]; then 
    POSITIONALPARAM=(${POSITIONALPARAM[@]} $1) 
    shift 
    OPTIND=1 
    fi 
done 

echo ${POSITIONALPARAM[@]} 

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

Как показано, я объясняю, что сдвиг удаляет первый аргумент (необязательный или нет) и перемещает все одно положение влево. $1 удален, $2 будет $1, $3 будет $2 и т.п. и т.п. Это дает скрипту контроль над перемещением необязательного аргумента, пока он не станет $1.

И shift, и сброс OPTIND сделать это возможным. Благодаря Chrono Kitsune для предположения, что OPTIND следует сбросить 1 вместо 0.

./sample.bash -a one -p two more -d sample

Выход:

one 
two 
Option d 
more sample 

Теперь давайте назовем сценарий с аргументами в различных положениях.

./sample.bash more -a one -p two -d sample

Выход:

one 
two 
Option d 
more sample 
+1

'OPTIND' должно быть 1, а не 0. Вероятно, также неплохо было бы отметить, где« shift »есть, так как они имеют решающее значение для этого метода. –

+0

OPTIND может быть 0 или 1, если он не больше 1. Единственным требованием является сброс OPTIND. Однако, если вы знаете, что существует реализация, где установка OPTIND на 0 не работает, тогда мне придется начать сброс до 1 вместо 0, как я привык. И спасибо, что нашли время, чтобы сообщить мне.Знание - сила. – alvits

+1

«Если приложение устанавливает OPTIND в значение 1, может быть использован новый набор параметров ... Любая другая попытка вызвать getopts ... с значением OPTIND, измененным как значение, отличное от 1, производит неуказанные результаты». [(Источник)] (http://pubs.opengroup.org/onlinepubs/7999959899/utilities/getopts.html) –

 Смежные вопросы

  • Нет связанных вопросов^_^