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âtgetopts
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
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 caoptions "$@"
. - 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 lawhile (( "$#" ))
+=
cu o matrice. Nu ' nu știați că puteți face asta. Frumos!