Cum pot gestiona comutatoarele într-un script shell?

Există câteva instrumente încorporate care vor recunoaște -x și --xxxx ca comutatoare, și nu argumente, sau trebuie să parcurgeți toate variabilele de intrare, să testați liniuțele și apoi să analizați argumentele ulterior?

Răspundeți

Utilizați getopts .

Este destul de portabil așa cum este în specificația POSIX. Din păcate, nu acceptă opțiuni lungi.

Consultați și acest getopts tutorial prin amabilitatea lui wiki-ul bash-hackers și această întrebare din stackoverflow.

Dacă aveți nevoie doar de opțiuni scurte, model tipic de utilizare pentru getopts (folosind raportarea non-silențioasă a erorilor) este:

# 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 

Comentarii

  • Ar trebui menționat faptul că getopt trebuie verificat întotdeauna ca GNU getopt înainte de a-l utiliza, dar nu ar trebui să ' să-l utilizați oricum întrucât getopts este oricum mai portabil (și, în general, mai drăguț). Dacă aveți nevoie să-l apelați dintr-un anumit motiv, apelați-l într-un mod specific GNU, și asigurați-vă că GETOPT_COMPATIBLE nu se află în mediu.
  • Ce face colonul din while getopts "ab:" opt?
  • @ user394 : după ce o literă opțională o semnifică necesită un argument. A : ca primul caracter înseamnă a suprima mesajele de eroare.

Răspuns

Presupun că folosiți bash sau similar. Un exemplu:

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

Comentarii

  • +1 pentru utilizarea += cu o matrice. Nu ' nu știați că puteți face asta. Frumos!

Răspuns

Trebuie să scrieți un ciclu pentru a analiza parametrii. Într-adevăr, puteți utiliza getopts comanda pentru a o face cu ușurință.

Acesta este un exemplu simplu din pagina de manual getopts:

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

Răspuns

Am scris recent un script pentru lucrări care era versatil și permis pentru mai multe tipuri de comutatoare în orice ordine. Nu pot dezvăluie scenariul complet din motive juridice evidente (ca să nu mai vorbesc că nu îl am cu mine în acest moment), dar aici e carnea lui .. poți să-l pui n un subrutină și apelați-l la sfârșitul scriptului:

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 

Vă recomand să vă limitați scriptul bash la mai puțin de 400 de linii / 15k caractere; scenariul meu menționat anterior a depășit această dimensiune și a devenit foarte greu de lucrat. Am început să-l rescriu în Perl, care este mult mai potrivit pentru sarcină. Rețineți acest lucru în timp ce lucrați la scripturile dvs. în bash. Bash este excelent pentru scripturi mici și onelinere, dar orice lucru mai complex și este mai bine să-l scrieți în Perl.

Notă, nu am testat cele de mai sus, așa că probabil nu funcționează, dar obțineți ideea generală din ea.

Comentarii

  • Modul în care apelați options la sfârșit nu este corect, va reveni -bash: syntax error near unexpected token $@. Apelați-l ca options "$@".
  • Da, am amestecat Perl și Bash. Corectat.
  • Această condiție while nu ar trebui să fie (($#))?
  • De ce ai avea nevoie de două seturi de paranteze pentru $#? Editați: aveți dreptate '. Ați remediat-o la while (( "$#" ))

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *