Hvordan håndterer jeg brytere i et skallskript?

Er det noen innebygde verktøy som vil gjenkjenne -x og --xxxx som brytere, og ikke argumenter, eller må du gå gjennom alle inngangsvariablene, teste for bindestreker, og deretter analysere argumentene deretter?

Svar

Bruk getopts .

Det er ganske bærbar som den er i POSIX-spesifikasjonen. Dessverre støtter den ikke lange alternativer.

Se også denne getopts tutorial med tillatelse fra bash-hackers wiki og dette -spørsmålet fra stackoverflow.

Hvis du bare trenger korte alternativer, er det vanlig bruksmønster for getopts (bruker ikke-lydløs feilrapportering) 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 bør nevnes at getopt alltid skal verifiseres som GNU getopt før du bruker den, men du bør ikke ' ikke bruke den uansett ettersom getopts uansett er mer bærbar (og generelt finere). Hvis du gjør det trenger å ringe det av en eller annen grunn, kan du kalle det på en GNU-spesifikk måte, og sørg for at GETOPT_COMPATIBLE ikke er i miljøet.
  • Hva gjør kolon i while getopts "ab:" opt?
  • @ user394 : etter en alternativ bokstav betyr det krever et argument. Et : som første tegn betyr å undertrykke feilmeldinger.

Svar

Jeg antar at du bruker 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 for å bruke += med en matrise. Visste ' ikke at du kunne gjøre det. Hyggelig!

Svar

Du må skrive en syklus for å analysere parametrene. Du kan faktisk bruke getopts kommando om å gjøre det enkelt.

Dette er et enkelt eksempel fra getopts manuell 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 skript nylig for arbeid som var allsidig og tillatt for flere typer brytere i hvilken som helst rekkefølge. Jeg kan ikke avslør hele skriptet av åpenbare juridiske grunner (for ikke å nevne at jeg ikke har det med meg for øyeblikket), men her er kjøttet av det .. du kan si det jeg n en underrutine og kall den på slutten av skriptet ditt:

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 å begrense ditt bash-skript til mindre enn 400 linjer / 15 000 tegn; mitt nevnte manus vokste forbi denne størrelsen og ble veldig vanskelig å jobbe med. Jeg begynte å omskrive den i Perl, noe som er mye bedre egnet for oppgaven. Husk det når du jobber med skriptene dine i bash. Bash er flott for små skript og onelinere, men alt mer komplekst, og det er bedre å skrive det i Perl.

Merk, jeg har ikke teste det ovennevnte, så det virker sannsynligvis ikke, men du får den generelle ideen av det.

Kommentarer

  • Slik du ringer options på slutten ikke stemmer, vil den returnere -bash: syntax error near unexpected token $@. Kall det som options "$@".
  • Yup, jeg blandet sammen Perl og Bash. Rettet.
  • At while tilstand ikke skal være (($#)) i stedet?
  • Hvorfor trenger du to paranteser for $#? Rediger: du ' har rett. Fikset det til while (( "$#" ))

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *