Wie kann ich einem Shell-Skript eine Hilfemethode hinzufügen?
128
Wie überprüfe ich, ob ein -hAttribut an ein Shell-Skript übergeben wurde? Ich möchte eine Hilfemeldung anzeigen, wenn ein Benutzer anruftmyscript.sh -h .
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=42while getopts ':hs:' option;docase"$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;;esacdone
shift $((OPTIND -1))
So verwenden Sie dies innerhalb einer Funktion:
verwenden "$FUNCNAME"statt$(basename "$0")
local OPTIND OPTARGvor dem Anruf hinzufügengetopts
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
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:docase"$1"in-r |--resolution)if[ $# -ne 0 ]; then
resolution="$2"# You may want to check validity of $2fi
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 optionsbreak;;esacdone###################### # 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:
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.
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.
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 .
Antworten:
Hier ist ein Beispiel für Bash:
So verwenden Sie dies innerhalb einer Funktion:
"$FUNCNAME"
statt$(basename "$0")
local OPTIND OPTARG
vor dem Anruf hinzufügengetopts
quelle
basename
mit dem führenden Strich weiterzugeben ."$FUNCNAME"
nicht verwenden"$0"
.local OPTIND OPTARG
FUNCNAME
funktioniert. 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."$usage"
jeden Ort zitieren, an dem Sie es verwenden.shift $((OPTIND - 1))
?Das erste Argument für ein Shell-Skript ist als Variable verfügbar
$1
, daher wäre die einfachste ImplementierungAber was Anubhava gesagt hat.
quelle
[
die POSIX-kompatible Version ist.function
: Sie sollten ersetzenexit 0
mit ,return
wenn Sie nicht möchten , dass Ihre Shell beenden , nachdem Ihre Funktion auszuführen. (Ich habe es schon mal gemacht 😂)Hier ist ein Teil, mit dem ich einen VNC-Server starte
Es ist ein bisschen komisch, dass ich den Start-Stopp-Neustart in einem separaten Fall platziert habe, aber es sollte funktionieren
quelle
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 eineif
mit einem Test ([
). Beispielsweise:Beachten Sie, dass die Posix-Kompatibilität
=
genauso gut funktioniert wie==
.Warum zitieren
$1
?Der Grund, warum
$1
in Anführungszeichen gesetzt werden muss, ist, dass$1
die Shell , wenn keine vorhanden ist , versucht, auszuführenif [ == "-h" ]
und fehlzuschlagen, da==
nur ein einziges Argument angegeben wurde, als zwei erwartet wurden:Für etwas komplexere Verwendung
getopt
odergetopts
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
getopt
Programm anstelle der integrierten Shell berücksichtigengetopts
. Es ermöglicht die Verwendung langer Optionen und Optionen nach Argumenten ohne Option (z. B.foo a b c --verbose
anstatt nurfoo -v a b c
). Diese Stackoverflow-Antwort erklärt die Verwendung von GNUgetopt
.† jeffbyrnes erwähnt , dass der Original - Link starb aber zum Glück der Art und Weise zurück Maschine hatte es archiviert.
quelle
Besser die getopt-Funktion von bash verwenden. Weitere Hilfe finden Sie in diesen Fragen und Antworten : Verwenden von getopts im Bash-Shell-Skript, um lange und kurze Befehlszeilenoptionen zu erhalten
quelle
Ich denke, Sie können Fall für diesen verwenden ...
quelle