Wie kann ich einem Shell-Skript eine Hilfemethode hinzufügen?


Antworten:


173

Hier ist ein Beispiel für Bash:

usage="$(basename "$0") [-h] [-s n] -- program to calculate the answer to life, the universe and everything

where:
    -h  show this help text
    -s  set the seed value (default: 42)"

seed=42
while getopts ':hs:' option; do
  case "$option" in
    h) echo "$usage"
       exit
       ;;
    s) seed=$OPTARG
       ;;
    :) printf "missing argument for -%s\n" "$OPTARG" >&2
       echo "$usage" >&2
       exit 1
       ;;
   \?) printf "illegal option: -%s\n" "$OPTARG" >&2
       echo "$usage" >&2
       exit 1
       ;;
  esac
done
shift $((OPTIND - 1))

So verwenden Sie dies innerhalb einer Funktion:

  • verwenden "$FUNCNAME"statt$(basename "$0")
  • local OPTIND OPTARGvor dem Anruf hinzufügengetopts

1
Ich versuche dies innerhalb einer Funktion, aber wenn ich versuche, die Funktion auszuführen, erhalte ich die Fehlermeldung "Basisname: ungültige Option - 'b'". Es sieht so aus, als würde versucht, "-bash" basenamemit dem führenden Strich weiterzugeben .
Morgan Estes

5
Imside eine Funktion "$FUNCNAME"nicht verwenden "$0". local OPTIND OPTARG
Fügen Sie

Vielen Dank. FUNCNAMEfunktioniert. Ich habe alle meine Funktionen in einer einzigen Datei, daher ist dies perfekt, um sie zu etwas zu erweitern, das für andere nützlich ist.
Morgan Estes

5
@sigur, stellen Sie sicher, dass Sie "$usage" jeden Ort zitieren, an dem Sie es verwenden.
Glenn Jackman

1
Wofür ist das shift $((OPTIND - 1))?
Hpaknia

45

Das erste Argument für ein Shell-Skript ist als Variable verfügbar $1, daher wäre die einfachste Implementierung

if [ "$1" == "-h" ]; then
  echo "Usage: `basename $0` [somestuff]"
  exit 0
fi

Aber was Anubhava gesagt hat.


Vielen Dank an MarkBooth, Tippfehler korrigiert (plus Verbesserung durch Anführungszeichen)
7.

Sie sollten es sich zur Gewohnheit machen, das if in [[...]] für Bedingungen zu verpacken, um ein schlechtes Parsen einer Variablen zu vermeiden. Quelle: github.com/bahamas10/bash-style-guide#bashisms
JREAM

2
Ja, obwohl das OP keine Bash angegeben hat und [die POSIX-kompatible Version ist.
20.

Hinweis - innen mit function: Sie sollten ersetzen exit 0mit , returnwenn Sie nicht möchten , dass Ihre Shell beenden , nachdem Ihre Funktion auszuführen. (Ich habe es schon mal gemacht 😂)
Illuminator

29

Hier ist ein Teil, mit dem ich einen VNC-Server starte

#!/bin/bash
start() {
echo "Starting vnc server with $resolution on Display $display"
#your execute command here mine is below
#vncserver :$display -geometry $resolution
}

stop() {
echo "Killing vncserver on display $display"
#vncserver -kill :$display
}

#########################
# The command line help #
#########################
display_help() {
    echo "Usage: $0 [option...] {start|stop|restart}" >&2
    echo
    echo "   -r, --resolution           run with the given resolution WxH"
    echo "   -d, --display              Set on which display to host on "
    echo
    # echo some stuff here for the -a or --add-options 
    exit 1
}

################################
# Check if parameters options  #
# are given on the commandline #
################################
while :
do
    case "$1" in
      -r | --resolution)
          if [ $# -ne 0 ]; then
            resolution="$2"   # You may want to check validity of $2
          fi
          shift 2
          ;;
      -h | --help)
          display_help  # Call your function
          exit 0
          ;;
      -d | --display)
          display="$2"
           shift 2
           ;;

      -a | --add-options)
          # do something here call function
          # and write it in your help function display_help()
           shift 2
           ;;

      --) # End of all options
          shift
          break
          ;;
      -*)
          echo "Error: Unknown option: $1" >&2
          ## or call function display_help
          exit 1 
          ;;
      *)  # No more options
          break
          ;;
    esac
done

###################### 
# Check if parameter #
# is set too execute #
######################
case "$1" in
  start)
    start # calling function start()
    ;;
  stop)
    stop # calling function stop()
    ;;
  restart)
    stop  # calling function stop()
    start # calling function start()
    ;;
  *)
#    echo "Usage: $0 {start|stop|restart}" >&2
     display_help

     exit 1
     ;;
esac

Es ist ein bisschen komisch, dass ich den Start-Stopp-Neustart in einem separaten Fall platziert habe, aber es sollte funktionieren


wenn Sie -d eine leere Option geben; wird es nicht Endlosschleife?
Zerobane

17

Verwenden Sie für eine schnelle Lösung mit nur einer Option if

Wenn Sie nur eine Option prüfen müssen und dies immer die erste Option ist ( $1), ist die einfachste Lösung eine ifmit einem Test ( [). Beispielsweise:

if [ "$1" == "-h" ] ; then
    echo "Usage: `basename $0` [-h]"
    exit 0
fi

Beachten Sie, dass die Posix-Kompatibilität =genauso gut funktioniert wie ==.

Warum zitieren $1?

Der Grund, warum $1in Anführungszeichen gesetzt werden muss, ist, dass $1die Shell , wenn keine vorhanden ist , versucht, auszuführen if [ == "-h" ]und fehlzuschlagen, da ==nur ein einziges Argument angegeben wurde, als zwei erwartet wurden:

$ [ == "-h" ]
bash: [: ==: unary operator expected

Für etwas komplexere Verwendung getoptodergetopts

Wie vorgeschlagen , durch andere , wenn Sie mehr als eine einzige einfache Möglichkeit haben, oder benötigen eine Option ein Argument zu akzeptieren, dann sollten Sie auf jeden Fall für die zusätzliche Komplexität der Verwendung zu gehen getopts.

Als Kurzreferenz gefällt mir das 60-Sekunden-Tutorial .

Möglicherweise möchten Sie auch das getoptProgramm anstelle der integrierten Shell berücksichtigen getopts. Es ermöglicht die Verwendung langer Optionen und Optionen nach Argumenten ohne Option (z. B. foo a b c --verboseanstatt nur foo -v a b c). Diese Stackoverflow-Antwort erklärt die Verwendung von GNU getopt.

jeffbyrnes erwähnt , dass der Original - Link starb aber zum Glück der Art und Weise zurück Maschine hatte es archiviert.


Vielen Dank! Ich benutze getopts seit einem Jahr gerne, aber ich werde mir auch getopt ansehen.
tttppp

1
Leider ist der Link zu The 60 Second getopts Tutorial tot; es scheint, dass bashcurescancer.com nicht mehr ist. Hier ist ein Link zur Version der Wayback-Maschine .
Jeffbyrnes


-1

Ich denke, Sie können Fall für diesen verwenden ...

case $1 in 
 -h) echo $usage ;; 
  h) echo $usage ;;
help) echo $usage ;;
esac
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.