Hur hanterar jag växlar i ett skalskript?

Finns det några inbyggda verktyg som känner igen -x och --xxxx som växlar och inte som argument, eller måste du gå igenom alla inmatningsvariabler, testa för bindestreck och sedan analysera argumenten därefter?

Svara

Använd getopts .

Det är ganska bärbar som den är i POSIX-specifikationen. Tyvärr stöder det inte långa alternativ.

Se även denna getopts handledning med tillstånd av bash-hackers wiki och denna fråga från stackoverflow.

Om du bara behöver korta alternativ, typiskt användningsmönster för getopts (använder icke-tyst felrapportering) är:

# 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 nämnas att getopt alltid ska verifieras eftersom GNU getopt innan du använder den, men du ska inte ' inte använda den ändå eftersom getopts är mer bärbar (och i allmänhet trevligare) hur som helst. Om du gör det behöver du ringa det av någon anledning, ring det på ett GNU-specifikt sätt, och se till att GETOPT_COMPATIBLE inte finns i miljön.
  • Vad gör kolon i while getopts "ab:" opt?
  • @ user394 : efter en alternativbokstav betyder det kräver ett argument. A : som första tecken betyder att undertrycka felmeddelanden.

Svar

Jag antar att du använder bash eller liknande. Ett exempel:

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 för att använda += med en matris. Visste ' inte att du kunde göra det. Trevligt!

Svar

Du måste skriva en cykel för att analysera parametrarna. Du kan faktiskt använda getopts kommando för att göra det enkelt.

Detta är ett enkelt exempel från getopts manuell sida:

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

Jag skrev nyligen ett manus för arbete som var mångsidigt och tillåtet för flera typer av växlar i valfri ordning. Jag kan inte avslöja hela manuset av uppenbara juridiska skäl (för att inte tala om att jag inte har det med mig just nu), men här är köttet av det .. du kan uttrycka det jag n en underrutin och kalla den i slutet av ditt skript:

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 

Jag rekommenderar att du begränsar ditt bash-skript till mindre än 400 rader / 15 000 tecken; mitt ovannämnda manus växte förbi denna storlek och blev mycket svårt att arbeta med. Jag började skriva om den i Perl, vilket passar mycket bättre för uppgiften. Tänk på det när du arbetar med dina skript i bash. Bash är utmärkt för små manus och oneliners, men allt mer komplicerat och det är bättre att du skriver det i Perl.

Obs! Jag har inte testat ovanstående, så det fungerar antagligen inte, men du får den allmänna idén från den.

Kommentarer

  • Så som du ringer till options i slutet är inte korrekt, det kommer att returnera -bash: syntax error near unexpected token $@. Kalla det som options "$@".
  • Japp, jag blandade ihop Perl och Bash. Korrigerad.
  • Det while villkoret bör inte vara (($#)) istället?
  • Varför skulle du behöva två parantesparenteser för $#? Redigera: du ' har rätt. Fixade det till while (( "$#" ))

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *