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å eftersomgetopts
ä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 attGETOPT_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
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 somoptions "$@"
. - 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 tillwhile (( "$#" ))
+=
med en matris. Visste ' inte att du kunde göra det. Trevligt!