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 dagetopts
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, atGETOPT_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
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 somoptions "$@"
. - 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 tilwhile (( "$#" ))
+=
med et array. Vidste ' ikke, du kunne gøre det. Dejligt!