Hvordan håndterer jeg switche i et shell-script?

Er der nogle indbyggede værktøjer, der genkender -x og --xxxx som switche og ikke argumenter, eller skal du gennemgå alle inputvariablerne, teste for bindestreger og derefter analysere argumenterne derefter?

Svar

Brug getopts .

Det er retfærdigt bærbar som den er i POSIX-specifikationen. Desværre understøtter det ikke lange muligheder.

Se også denne getopts tutorial med tilladelse til bash-hackers wiki og dette spørgsmål fra stackoverflow.

Hvis du kun har brug for korte muligheder, er et typisk brugsmønster for getopts (ved hjælp af ikke-lydløs fejlrapportering) er:

# process arguments "$1", "$2", ... (i.e. "$@") while getopts "ab:" opt; do case $opt in a) aflag=true ;; # Handle -a b) barg=$OPTARG ;; # Handle -b argument \?) ;; # Handle error: unknown option or missing required argument. esac done 

Kommentarer

  • Det skal nævnes, at getopt altid skal bekræftes, da GNU getopt før du bruger det, men du skal ikke ' ikke bruge det alligevel da getopts alligevel er mere bærbar (og generelt pænere). Hvis du gør har brug for at kalde det af en eller anden grund, skal du kalde det på en GNU-specifik måde og sørg for, at GETOPT_COMPATIBLE ikke er i miljøet.
  • Hvad gør kolon i while getopts "ab:" opt?
  • @ user394 : efter et valgbogstav betyder det kræver et argument. Et : som det første tegn betyder at undertrykke fejlmeddelelser.

Svar

Jeg antager, at du bruger bash eller lignende. Et eksempel:

all=false long=false while getopts ":hal" option; do case $option in h) echo "usage: $0 [-h] [-a] [-l] file ..."; exit ;; a) all=true ;; l) long=true ;; ?) echo "error: option -$OPTARG is not implemented"; exit ;; esac done # remove the options from the positional parameters shift $(( OPTIND - 1 )) ls_opts=() $all && ls_opts+=( -a ) $long && ls_opts+=( -l ) # now, do it ls "${ls_opts[@]}" "$@" 

Kommentarer

  • +1 til brug af += med et array. Vidste ' ikke, du kunne gøre det. Dejligt!

Svar

Du skal skrive en cyklus for at parse parametrene. Faktisk kan du bruge getopts kommando til at gøre det let.

Dette er et simpelt eksempel fra getopts manuel side:

aflag= bflag= while getopts ab: name do case $name in a) aflag=1;; b) bflag=1 bval="$OPTARG";; ?) printf "Usage: %s: [-a] [-b value] args\n" $0 exit 2;; esac done if [ ! -z "$aflag" ]; then printf "Option -a specified\n" fi if [ ! -z "$bflag" ]; then printf "Option -b "%s" specified\n" "$bval" fi shift $(($OPTIND - 1)) printf "Remaining arguments are: %s\n" "$*" 

Svar

Jeg skrev et script for nylig til arbejde, der var alsidigt og tilladt for flere slags switches i enhver rækkefølge. Jeg kan ikke t afslør det fulde script af åbenlyse juridiske grunde (for ikke at nævne, at jeg ikke har det med mig i øjeblikket), men her er kødet af det .. du kan sætte det i n en underrutine, og kald den i slutningen af dit script:

options () { if [ -n "$1" ]; then # test if any arguments passed - $1 will always exist while (( "$#" )); do # process ALL arguments if [ "$1" = ^-t$ ]; then # -t short for "test" # do something here THEN shift the argument # shift removes it from $@ and reduces $# by # one if you supply no argument shift # we can also process multiple arguments at once elif [[ "$1" =~ ^--test=[:alnum:]{1,8}$ ]] && [[ "$2" =~ ^-t2$ ]] && [[ -n "$3" ]]; then # check for 3 arguments # do something more then remove them ALL from the arg list shift 3 else echo "No matching arguments!" echo "Usage: [script options list here]" fi done else echo "Usage: [script options list here]" exit 0 fi } options "$@" # run options and loop through/process ALL arguments 

Jeg anbefaler at begrænse dit bash-script til mindre end 400 linjer / 15k tegn; mit førnævnte script voksede forbi denne størrelse og blev meget vanskeligt at arbejde på. Jeg begyndte at omskrive den i Perl, hvilket er meget bedre egnet til opgaven. Husk det, når du arbejder på dine scripts i bash. Bash er fantastisk til små scripts og onelinere, men alt mere komplekst, og du skriver det bedre i Perl.

Bemærk, jeg har ikke teste ovenstående, så det virker sandsynligvis ikke, men du får den generelle idé af det.

Kommentarer

  • Sådan kalder du options i slutningen er ikke korrekt, det returnerer -bash: syntax error near unexpected token $@. Kald det som options "$@".
  • Yup, jeg blandede Perl sammen og Bash. Korrigeret.
  • At while betingelse ikke skal være (($#)) i stedet?
  • Hvorfor har du brug for to sæt parenteser til $#? Rediger: du ' har ret. Rettet det til while (( "$#" ))

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *