Jak obsługiwać przełączniki w skrypcie powłoki?

Czy są jakieś wbudowane narzędzia, które rozpoznają -x i --xxxx jako przełączniki, a nie argumenty, czy też musisz przejść przez wszystkie zmienne wejściowe, sprawdzić myślniki, a następnie przeanalizować argumenty?

Odpowiedź

Użyj getopts .

To jest sprawiedliwe przenośny, jak jest w specyfikacji POSIX. Niestety nie obsługuje on długich opcji.

Zobacz także ten getopts samouczek dzięki uprzejmości wiki bash-hackers i to pytanie ze stackoverflow.

Jeśli potrzebujesz tylko krótkich opcji, typowy wzorzec użycia dla getopts (przy użyciu cichego raportowania błędów) to:

# 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 

Komentarze

  • Należy wspomnieć, że getopt powinien być zawsze zweryfikowany jako GNU getopt przed jego użyciem, ale nie należy go ' i tak używać ponieważ getopts i tak jest bardziej przenośny (i ogólnie przyjemniejszy). Jeśli tak musisz go nazwać z jakiegoś powodu, nazwij go w sposób właściwy dla GNU, i upewnij się, że GETOPT_COMPATIBLE nie znajduje się w środowisku.
  • Co oznacza dwukropek w while getopts "ab:" opt?
  • @ user394 : po literze opcji oznacza to wymaga argumentu. : jako pierwszy znak oznacza pominięcie komunikatów o błędach.

Odpowiedź

Zakładam, że „używasz basha lub podobnego. Przykład:

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

Komentarze

  • +1 za używanie += z tablicą. Nie ' nie wiedziałem, że możesz to zrobić. Świetnie!

Odpowiedź

Musisz napisać cykl, aby przeanalizować parametry. Rzeczywiście, możesz użyć getopts, aby zrobić to łatwo.

To jest prosty przykład ze strony podręcznika 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" "$*" 

Answer

Niedawno napisałem skrypt do pracy, który był wszechstronny i pozwalał na wiele rodzajów przełączników w dowolnej kolejności. Nie mogę ujawnij pełny scenariusz z oczywistych względów prawnych (nie wspominając o tym, że w tej chwili nie mam go przy sobie), ale oto jego istota. n podprocedurą i wywołaj ją na końcu skryptu:

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 

Polecam ograniczenie twojego skryptu bash do mniej niż 400 linii / 15k znaków; mój wyżej wymieniony skrypt przekroczył ten rozmiar i stał się bardzo trudny w pracy. Zacząłem przepisywać to w Perlu, który jest znacznie lepiej dostosowany do tego zadania. Miej to na uwadze podczas pracy nad skryptami w bashu. Bash świetnie nadaje się do małych skryptów i onelinerów, ale jest bardziej złożony i lepiej napisać go w Perlu.

Uwaga, nie testowałem powyższego, więc prawdopodobnie nie działa, ale wyciągniesz z niego ogólny pomysł.

Komentarze

  • Sposób wywoływania options na końcu nie jest poprawne, zwróci -bash: syntax error near unexpected token $@. Nazwij to options "$@".
  • Tak, pomieszałem Perla i Bash. Poprawione.
  • Ten warunek while nie powinien być (($#))?
  • Dlaczego czy potrzebujesz dwóch zestawów nawiasów dla $#? Edycja: masz ' dobrze. Naprawiono to na while (( "$#" ))

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *