Come si gestiscono le opzioni in uno script di shell?

Esistono strumenti integrati in grado di riconoscere -x e --xxxx come opzioni e non argomenti, oppure devi esaminare tutte le variabili di input, verificare i trattini e quindi analizzare gli argomenti in seguito?

Risposta

Utilizza getopts .

È abbastanza portatile come nelle specifiche POSIX. Sfortunatamente non supporta opzioni lunghe.

Vedi anche questo getopts tutorial per gentile concessione di il wiki di bash-hackers e questa domanda da stackoverflow.

Se hai bisogno solo di opzioni brevi, modello di utilizzo tipico per getopts (utilizzando la segnalazione degli errori non silenziosa) è:

# 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 

Commenti

  • Va detto che getopt dovrebbe sempre essere verificato come GNU getopt prima di usarlo, ma non dovresti ' usarlo comunque poiché getopts è comunque più portabile (e generalmente più carino). Se devi chiamarlo per qualche motivo, chiamalo in un modo specifico per GNU, e assicurati che GETOPT_COMPATIBLE non si trovi nellambiente.
  • Che cosa fanno i due punti in while getopts "ab:" opt?
  • @ user394 Il : dopo una lettera di opzione lo indica richiede un argomento. Un : come primo carattere significa sopprimere i messaggi di errore.

Risposta

Presumo che tu stia usando bash o simili. Un esempio:

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[@]}" "$@" 

Commenti

  • +1 per aver utilizzato += con un array. ' non sapevo che potevi farlo. Bello!

Risposta

Devi scrivere un ciclo per analizzare i parametri. Infatti puoi usare getopts per farlo facilmente.

Questo è un semplice esempio tratto dalla getopts pagina di manuale:

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" "$*" 

Answer

Di recente ho scritto uno script per il lavoro che era versatile e consentiva più tipi di interruttori in qualsiasi ordine. Non posso “t divulgare la sceneggiatura completa per ovvie ragioni legali (per non parlare del fatto che al momento non ce lho con me), ma ecco il nocciolo della questione .. puoi metterlo in n una subroutine e chiamala alla fine del tuo 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 

Raccomando di limitare il tuo script bash a meno di 400 righe / 15k caratteri; il mio script di cui sopra è cresciuto oltre questa dimensione ed è diventato molto difficile da lavorare. Ho iniziato a riscriverlo in Perl, che è molto più adatto per il compito. Tienilo a mente mentre lavori sui tuoi script in bash. Bash è ottimo per piccoli script e oneliner, ma qualsiasi cosa più complessa e faresti meglio a scriverlo in Perl.

Nota, non ho testato quanto sopra, quindi probabilmente non funziona, ma ne ricavi lidea generale.

Commenti

  • Il modo in cui chiami options alla fine non è corretto, restituirà -bash: syntax error near unexpected token $@. Chiamalo options "$@".
  • Sì, ho mescolato Perl e Bash. Corretto.
  • Quella while condizione non dovrebbe essere (($#))?
  • Perché avresti bisogno di due serie di parentesi per $#? Modifica: ' hai ragione. Risolto il problema con while (( "$#" ))

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *