Verwenden von getopts zum Parsen von Optionen nach einem Argument ohne Option

10

Ich habe ein Bash-Skript wie unten in einer Datei nepleaks_upd.sh, als die ich ausführen möchte ./nepleaks_upd.sh bootstrap --branch off. Konnte es nicht schaffen zu nehmen --branch, aber was es funktioniert ist ./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         

Ohne zuerst case .. in .... esacfunktioniert es gut. Mit case ... in ... esacgibt es eine leere Option für -b,

$ ./nepleaks_upd.sh bootstrap -b off
option1 = ?
option2 = 
Usage: ./nepleaks_upd.sh [bootstrap | up | down]  [-b <on/off>]
betenagupd
quelle
Sollten Sie nicht vor der Verwendung nach Optionen suchen $1?
Unxnut
@unxnut Es singt Samething Bro
Prayagupd
Was meinst du mit "Ohne zuerst case .. in .... esacfunktioniert es gut"? Meinen Sie damit, dass die Zeilen 5-25 ./nepleaks_upd.sh -b offkorrekt analysiert werden? Vielleicht brauchst du eine shift, damit du getoptsnicht am " bootstrap" erstickst .
Scott
@ Scott Ja, genau dieser Teil funktioniert gut.
Prayagupd

Antworten:

12

getoptsStartet die Analyse beim ersten Argument und stoppt bei den ersten Argumenten ohne Option. Das ist die Standardkonvention - einige GNU Utilities Optionen nach Argumente akzeptieren, aber die normale Sache ist , dass in somecommand foo -bar qux, -barwird nicht als Option analysiert.

Wenn Sie danach mit dem Parsen von Optionen beginnen möchten bootstrap, müssen Sie dies angeben. getoptsverwendet die OPTINDVariable, um sich zu merken, an welcher Position sie sich befindet. OPTINDBeginnt mit dem Wert 1. Um das erste Argument zu überspringen, setzen Sie es auf 2.

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

Alternativ können Sie shiftdie Argumente verwenden, die Sie bereits verarbeitet haben.

subcommand=$1; shift
case "$subcommand" in
    bootstrap)
      while getopts ":b:" o; do
          
Gilles 'SO - hör auf böse zu sein'
quelle