Wie gehe ich mit Schaltern in einem Shell-Skript um?

Gibt es einige integrierte Tools, die -x und --xxxx als Schalter und nicht als Argumente, oder müssen Sie alle Eingabevariablen durchgehen, nach Bindestrichen suchen und anschließend die Argumente analysieren?

Antwort

Verwenden Sie getopts .

Es ist fair tragbar wie es in der POSIX-Spezifikation ist. Leider werden lange Optionen nicht unterstützt.

Siehe auch dieses getopts Tutorial mit freundlicher Genehmigung von das Bash-Hacker-Wiki und diese Frage aus dem Stackoverflow.

Wenn Sie nur kurze Optionen benötigen, typisches Verwendungsmuster für getopts (unter Verwendung einer nicht stillen Fehlerberichterstattung) lautet:

# 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 

Kommentare

  • Es sollte erwähnt werden, dass getopt immer als GNU getopt überprüft werden sollte, bevor Sie es verwenden, aber Sie sollten es ' trotzdem nicht verwenden da getopts ohnehin portabler (und im Allgemeinen besser) ist. Wenn Sie es aus irgendeinem Grund aufrufen müssen, rufen Sie es auf GNU-spezifische Weise auf. und stellen Sie sicher, dass sich GETOPT_COMPATIBLE nicht in der Umgebung befindet.
  • Was macht der Doppelpunkt in while getopts "ab:" opt?
  • @ user394 Die : nach einem Optionsbuchstaben kennzeichnet dies erfordert ein Argument. Ein : als erstes Zeichen bedeutet, Fehlermeldungen zu unterdrücken.

Antwort

Ich gehe davon aus, dass Sie Bash oder ähnliches verwenden. Ein Beispiel:

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

Kommentare

  • +1 für die Verwendung von += mit einem Array. ' wusste nicht, dass Sie das tun können. Schön!

Antwort

Sie müssen einen Zyklus schreiben, um die Parameter zu analysieren. In der Tat können Sie getopts, um dies einfach zu tun.

Dies ist ein einfaches Beispiel aus der getopts Handbuchseite:

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

Antwort

Ich habe kürzlich ein Skript für Arbeiten geschrieben, das vielseitig ist und mehrere Arten von Schaltern in beliebiger Reihenfolge zulässt. Ich kann nicht Geben Sie das vollständige Skript aus offensichtlichen rechtlichen Gründen bekannt (ganz zu schweigen davon, dass ich es im Moment nicht bei mir habe), aber hier ist das Fleisch davon. Sie können es sagen, ich n eine Unterroutine und rufen Sie sie am Ende Ihres Skripts auf:

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 

Ich empfehle, Ihr Bash-Skript auf weniger als 400 Zeilen / 15.000 Zeichen zu beschränken. Mein oben genanntes Skript wuchs über diese Größe hinaus und es wurde sehr schwierig, daran zu arbeiten. Ich habe angefangen, es in Perl umzuschreiben, was für die Aufgabe viel besser geeignet ist. Denken Sie daran, wenn Sie in bash an Ihren Skripten arbeiten. Bash ist ideal für kleine Skripte und Oneliner, aber alles, was komplexer ist, und Sie sollten es besser in Perl schreiben.

Beachten Sie, dass ich das Obige nicht getestet habe, also funktioniert es wahrscheinlich nicht, aber Sie erhalten eine allgemeine Vorstellung davon.

Kommentare

  • So wie Sie am Ende options aufrufen ist nicht korrekt, es wird -bash: syntax error near unexpected token $@ zurückgegeben. Nennen Sie es als options "$@".
  • Ja, ich habe Perl und verwechselt Bash. Korrigiert.
  • Diese while Bedingung sollte nicht stattdessen (($#)) sein?
  • Warum Benötigen Sie zwei Sätze von Klammern für $#? Bearbeiten: Sie ' haben Recht. Es wurde auf while (( "$#" ))

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.