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

10

У меня есть скрипт bash, как показано ниже в файле nepleaks_upd.sh, который я хочу запустить как ./nepleaks_upd.sh bootstrap --branch off. Не могу заставить его взять --branch, но то, что он работает, это ./nepleaks_upd.sh bootstrap -b off.

usage() { echo "Usage: $0 [prepare | up | down]  [-b <on/off>]" 1>&2; exit 1; }                                                                                                 

case "$1" in                                                                                           
               bootstrap)                                                                                  
                  while getopts ":b:" o; do                                                            
                   case "${o}" in                                                                      
                    b)                                                                                 
                        b=${OPTARG}                                                                    
                        if [ ${b} == "off" ]; then                                                      
                               echo "git clone https://github.com/iPrayag/dotfiles.git"  
                               ## logic                                                      
                        fi                                                                             
                        ;;                                                                             
                    *)                                                                                 
                        echo ${o}                                                                      
                        usage                                                                          
                        ;;                                                                             
                   esac                                                                                
                  done                                                                                 
                  shift $((OPTIND-1))                                                                  
                  echo "option1 = ${o}" 
                  echo "option2 = ${b}"                                                                      
                  if [ -z "${b}" ]; then                                                               
                         usage                                                                         
                  fi                                                                                   

                    ;;                                                                                 
                up)                                                                                         
                     echo "up"     
                     ##logic                                                                    
                     ;;                                                                                
                down)                                                                                  
                     echo "down" 
                     ##logic                                                                     
                    ;;                                                                                 
                *)                                                                                     
                    echo "Usage: $0 {up | down} dev"                                                
                    exit 1                                                                             
                    ;;                                                                                 
esac         

Без первого case .. in .... esacвсе работает нормально. С case ... in ... esac, это дает пустую опцию для -b,

$ ./nepleaks_upd.sh bootstrap -b off
option1 = ?
option2 = 
Usage: ./nepleaks_upd.sh [bootstrap | up | down]  [-b <on/off>]
prayagupd
источник
Разве вы не должны проверять варианты перед использованием $1?
unxnut
@unxnut Он поёт samething братан
prayagupd
Что вы подразумеваете под «без первого case .. in .... esac, он работает нормально»? Вы имеете в виду, что строки 5-25 ./nepleaks_upd.sh -b offправильно разбираются ? Может быть, вам нужно shift, так getoptsчто не подавиться " bootstrap".
Скотт
@ Скотт Да, именно эта часть работает отлично.
prayagupd

Ответы:

12

getoptsначинает синтаксический анализ первого аргумента и останавливается на первых аргументах без опций. Это стандартная конвенция - некоторые утилиты GNU принимать параметры после аргументов, но нормальная вещь в том , что в somecommand foo -bar qux, -barне разбираются в качестве опции.

Если вы хотите начать разбирать параметры после bootstrap, вам нужно указать это. getoptsиспользует OPTINDпеременную, чтобы запомнить, в каком положении она находится. OPTINDначинается со значения 1. Чтобы пропустить первый аргумент, установите его равным 2.

case "$1" in
   bootstrap)
      OPTIND=2
      while getopts ":b:" o; do
          

Кроме того, вы можете shiftаргументы, которые вы уже обработали.

subcommand=$1; shift
case "$subcommand" in
    bootstrap)
      while getopts ":b:" o; do
          
Жиль "ТАК - перестань быть злым"
источник