
getopts geeignet
getopt.ls beispiel.txt würde den Dateinamen einfach anzeigen,
sofern die Datei beispiel.txt vorhanden ist; wovon wir mal ausgehen.ls -l beispiel.txt zeigt uns ls mehr Informationen zur Datei an.ls,
im zweiten Fall kommt der Dateiname erst an dritter Stelle
auf der Kommandozeile. Da außerdem viel mehr Optionen zugleich angegeben werden dürfen, ist ls also
in der Lage, die Optionen vom Dateinamen zu unterscheiden, egal wie weit hinten der Dateiname steht.getopts
können auch Shellscripts dieses Feature erhalten.getopts gut geeignet.OPTSTR=':ab:c'Ein OptString beginnt immer mit einem Doppelpunkt (
:).
Im Beispiel werden die Optionen -a, -b und -c erwartet.
b bedeutet, dass b einen Wert erwartet.
getopts die Shellvariablen OPTIND
und OPTARG anlegt und beschreibt
MYOPT.getoptstest.sh aus# # getoptstest.sh # OPTSTR=':ab:c' getopts $OPTSTR MYOPT echo "$?", "$MYOPT", "$OPTIND", "$OPTARG"
$ getoptstest.sh -ack -b Hallo 0, a, 1,
getopts. Wenn 0,
dann wurde eine Option erkannt.MYOPT, und das ist im Beispiel die erkannte Option -a.OPTIND) gibt den Index des erkannten Worts auf der Kommandozeile an.
$1 finden.OPTARG) ist leer, seine Bedeutung wird in der Folge deutlich.getopts in gleicher Weise mehrmals aufruft
- darauf muss man erst mal kommen. Wir erweitern das Beispielscript:
OPTSTR=':ab:c' getopts $OPTSTR MYOPT echo "$?", "$MYOPT", "$OPTIND", "$OPTARG" getopts $OPTSTR MYOPT echo "$?", "$MYOPT", "$OPTIND", "$OPTARG" getopts $OPTSTR MYOPT echo "$?", "$MYOPT", "$OPTIND", "$OPTARG" getopts $OPTSTR MYOPT echo "$?", "$MYOPT", "$OPTIND", "$OPTARG"
$ getoptstest.sh -ack -b Hallo 0, a, 1, 0, c, 1, 0, ?, 2, k 0, b, 4, HalloDie Werte von
MYOPT lassen erkennen, dass die Optionen in gleicher Reihenfolge erkannt werden
wie auf der Kommandozeile notiert.-k eine Option, die wir im OptString nicht definiert haben.
Daher kennt getopts diese Option auch nicht, schreibt in MYOPT ein Fragezeichen ein
und die Option selbst in OPTARG.getopts-Aufruf wird -b erkannt, und sein Wert landet in OPTARG.
$ getoptstest.sh -ac 0, a, 1, 0, c, 2, 1, ?, 2, 1, ?, 2,Wird
getopts nach der letzten Option aufgerufen,
signalisiert der Rückgabewert ungleich 0 das Ende des Einlesens der Optionen.
0 wird in der Shellprogrammierung als logisch true interpretiert,
ungleich 0, uninteressant welche Zahl, als logisch false.$ getoptsbsp.sh -ac -ac 0, a, 1, 0, c, 2, 0, a, 2, 0, c, 3,Werden Optionen mehrfach angegeben, dann werden sie auch mehrfach gelesen.
$ getoptstest.sh -ac X -ac 0, a, 1, 0, c, 2, 1, ?, 2, 1, ?, 2,Eine separat notierte Zeichenkette, die nicht mit Minuszeichen beginnt (oder auch nur ein einzelnes Zeichen) wird richtigerweise nicht als Optionsangabe erkannt, sondern als Argument. Das Lesen von Optionen ist damit beendet. Da Optionen grundsätzlich vor Argumenten anzugeben sind, haben nachfolgende Optionsangaben auch keinen Zweck.
$ getoptstest.sh -ac -- -ac 0, a, 1, 0, c, 2, 1, ?, 3, 0, a, 3,Das Lesen der alleinstehenden Angabe
-- bewirkt ebenfalls
einen Rückgabwert ungleich 0. Zwar würden danach noch Optionen erkannt werden,
aber davon wird kein Gebrauch gemacht. Die Angabe wird als Optionsende-Kennzeichen verwendet.
Das heißt, alles, was danach kommt, egal wie geschrieben, sind Argumente.b einen Wert.
Wir lassen ihn mal weg.
$ getoptstest.sh -ack -b 0, a, 1, 0, c, 1, 0, ?, 2, k 0, :, 3, bBei fehlendem Options-Wert landet in
MYOPT ein Doppelpunkt
und die Option selbst wird in OPTARG abgelegt; $ getoptsbsp.sh -abc 0, a, 1, 0, b, 2, c 1, ?, 2, 1, ?, 2,Auch hier fehlt der Option ihr Wert. Allerdings wird die nächstbeste Zeichenkette als Wert verwendet, in diesem Fall das
c. Ist c als Wert gewollt, oder nicht?
Mit einer formalen Logik kaum für jede denkbare Situation aufzulösen.
getopts nicht unterstützt wird. getopts ergibt sich die Möglichkeit,
getopts-Aufrufe in eine Schleife einzubauen.
Solange die Rückgabe 0 ist (also logisch true), soll die Schleife laufen.
Unser Beispielscript wird nun sehr kurz:
OPTSTR=':ab:c' while getopts $OPTSTR MYOPT do echo "$?", "$MYOPT", "$OPTIND", "$OPTARG" doneGut als Testscript geeignet, um alle möglichen Szenarien durchzuspielen.
getopts
echo-Kommandos.
#
# basisscript-getopts.sh
#
OPTSTR=':ab:c'
while getopts $OPTSTR MYOPT
do
if [ "$MYOPT" == "?" ] && [ -n "$OPTARG" ]
then
# Reaktion auf unerwartete Option
echo "Option $OPTARG wurde nicht erwartet."
elif [ "$MYOPT" == ":" ] && [ -n "$OPTARG" ]
then
# Reaktion auf fehlendes Optionsargument
echo "Der Option $OPTARG fehlt der Wert ."
else
# Reaktion auf reguläre Option
echo -n "Option $MYOPT wurde erkannt"
if [ -n "$OPTARG" ]
then
# Reaktion auf Wert zur Option
echo -n " mit Wert $OPTARG"
fi
echo "."
fi
done
# Zugriff auf Argumente nach dem Lesen aller Optionen
shift $((OPTIND - 1))
if [ -n "$1" ]
then
# Argumente auswerten
echo "Argumente: $@"
fi
Die Auswertung von Argumenten ist nach der Schleife möglich.
In den Stellungsparametern jedoch stehen die Optionen und Argumente unverändert wie beim Aufruf drin.
Mit shift kann man die Werte der Stellungsparameter nach links wegschieben.
Am besten soweit, dass das erste Argument im Parameter $1 zu stehen kommt.
OPTIND. Nach allen gelesenen Optionen steht
darin der Index des ersten Arguments. Da wir dieses Argument nicht mit herausschieben
wollen, müssen wir um 1 weniger schieben als OPTIND ausweist.
Die Berechnung erledigt der Ausdruck $((OPTIND - 1)), und shift erhält
die richtige Anzahl Schubschritte.$1 (und die folgenden Stellungsparameter) leer.
Wenn jedoch etwas drin ist, genau das testet die letzte if-Anweisung,
dann findet man die Argumente in den Stellungsparametern ab $1.$ basisscript-getopts.sh -ack -b 25 Hallo, Welt Option a wurde erkannt. Option c wurde erkannt. Option k wurde nicht erwartet. Option b wurde erkannt mit Wert 25. Argumente: Hallo, Welt
s, aber
getopt ist ein anderes Kommando.
Dabei nicht einmal ein Shell-Builtin, sondern ein externes Kommando.
Die Anwendung ist eigentlich nur in Shellscripten sinnvoll,
daher könnte es uns interessieren. getopts.
getopt -o optstring -- parametersMit
optstring ist dasselbe gemeint wie der OptString bei getopts,
nämlich eine Angabe, welche Optionen vorkommen sollen. Das kann eine Folge von
Zeichenketten sein, daher zeigt -- das Ende an.parameters verbirgt sich die Folge von Optionen und Argumenten,
die man beim Kommandoaufruf angibt. Also:
-a, -b und -c.
Das notieren wir als OptString: -o abc.-a -bc Hallo Welt
getopt auf der Kommandozeile auf:
$ getopt -o abc -- -a -bc Hallo Welt -a -b -c -- 'Hallo' 'Welt'Wir sehen, dass
getopt ein Ergebnis ausgibt. Sieht im ersten Moment genau so aus wie
die Angaben hinter getopt, es gibt auch -- als Trennung.
Unterschiede: Vor der Trennung wurden die Optionen einzeln ausgegeben.
Danach sehen wir alle anderen Argumente, schön einzeln gequotet.
$ getopt -o abc -- -a Hallo -b Welt -c -a -b -c -- 'Hallo' 'Welt'Es erscheint dasselbe Ergebnis; getopt kann sortieren: die erkannten Optionen linksseitig von
--, alle anderen Argumente rechtsseitig.
Das heißt, wir haben die Freiheit, Optionen auch hinter Argumenten notieren zu können.getopt in ein ganz einfaches Testscript ein,
etwa so:
# # first-getopt-script.sh # getopt -o abc -- $@Der Shellparameter
$@ enthält die komplette Kommandozeile des Scriptaufrufs,
sodass alle Optionen und Argumente an dieser Stelle landen.
Wir wiederholen den letzten Test, jetzt aber mit dem Script:
$ first-getopt-script.sh -a Hallo -b Welt -c -a -b -c -- 'Hallo' 'Welt'Na bitte, die Optionen und Argumente vom Scriptaufruf werden genauso erkannt wie zuvor bei unserer Direkteingabe.
-a einen Wert zuordnen und ändern im Script den OptString ...
getopt -o a:bc -- $@
... und testen gleich mal:
$ first-getopt-script.sh -a 25 Hallo -b Welt -c -a '25' -b -c -- 'Hallo' 'Welt'Der Wert erscheint als Zeichenkette direkt hinter der Option
-a
$ first-getopt-script.sh -a Hallo -b Welt -c -a 'Hallo' -b -c -- 'Welt'Klar, es wird die nächstbeste Angabe als Wert genommen, das kennen wir schon von
getopts.
getopt noch ein echtes Ass im Ärmel.
getopt -o a::bc -- $@
$ first-getopt-script.sh -a Hallo -b Welt -c -a '' -b -c -- 'Hallo' 'Welt'
$ first-getopt-script.sh -a 25 Hallo -b Welt -c -a '' -b -c -- '25' 'Hallo' 'Welt'Nanu, der Wert erscheint auf der Seite der Argumente und hinter
-a steht die leere Zeichenkette.
$ first-getopt-script.sh -a25 Hallo -b Welt -c -a '25' -b -c -- 'Hallo' 'Welt'
getopt, wenn eine Option vorkommt, die nicht im Optstring definiert wurde?
$ first-getopt-script.sh -kbc Hallo Welt getopt: unknown option -- k -b -c -- 'Hallo' 'Welt'Es erscheint eine Fehlermeldung.
getopt.log)
$ first-getopt-script.sh -kbc Hallo Welt 2> getopt.log -b -c -- 'Hallo' 'Welt'dann sehen wir, dass die Fehlermeldung nicht im Ergebnis (Standardausgabe) landet,
$ cat getopt.log getopt: unknown option -- ksondern jetzt in der Datei.
getopt sortieren Optionen und Argumente in die Stellungsparameter.# # second-getopt-script.sh # echo $@ set -- $(getopt -o a::bc -- $@) echo $@Die
echo-Anweisungen zeigen alle Stellungsparameter an,
vor und nach dem set-Kommando.
set belegt die Stellungsparameter $1, $2 ,$3 usw.,
mit den angegebenen Zeichenketten, und zwar mit den Ergebnis-Zeichenketten von getopt.
Da set selbst Optionen kennt, wird zuerst das Optionenendezeichen -- notiert,
damit set nicht fälschlicherweise Teile des getopt-Ergebnisses als Optionen für sich interpretiert.$ second-getopt-script.sh -a Hallo Welt -bc -a Hallo Welt -bc -a '' -b -c -- 'Hallo' 'Welt'Das erste
echo zeigt die Parameter in der Reihenfolge an, die unserer Eingabe entspricht,
das zweite echo zeigt die Belegung der Parameter nach dem set-Kommando. echo-Kommandos
und durchlaufen die Stellungsparameter mit einer while-Schleife.
set -- $(getopt -o a::bc -- $@) while [ -n "$1" ] do echo "$1"; shift done
$1 gelesen, danach aber sofort die Parameter mit shift
nach links verschoben,
sodass der nächste Parameterwert in $1 landet und für den Folgedurchlauf zur Verfügung steht.
$ second-getopt-script.sh -a Hallo Welt -bc -a '' -b -c -- 'Hallo' 'Welt'Die Optionen und Argumente werden so einzeln durchlaufen, bis kein Wert mehr kommt und
$1 leer bleibt.
case die einzelnen Angaben finden und
auswerten. Im Beispiel wurden alle erwarteten Optionen und Werte Shellvariablen zugewiesen,
sodass eine Reaktion auf die Optionen nach der Schleife erfolgen kann,
hier nur mit einfachen echo-Ausgaben demonstriert.
set -- $(getopt -o a::bc -- $@)
while [ -n "$1" ]
do
case "$1" in
-a) # Option -a erkannt
A="$1"; shift
AW="$1"; shift
;;
-b) # Option -b erkannt
B="$1"; shift
;;
-c) # Option -c erkannt
C="$1"; shift
;;
--) # Ende der Optionen
shift; break
;;
esac
done
echo "Erkannte Optionen:"
echo "$A mit Wert $AW"
echo "$B"
echo "$C"
echo "Auswertung der Argumente:"
echo "$@"
Das Muster --) in case erkennt das
von getopt gelieferte Optionen-Endekennzeichen
break ab.$ second-getopt-script.sh -a25 -b Hallo Welt Erkannte Optionen: -a mit Wert '25' -b Auswertung der Argumente: 'Hallo' 'Welt'
-o OptString haben wir getopt mitgeteilt, welche Optionen in Kurzschreibweise
erkannt werden sollen. Optionen in Langschreibweise werden so definiert:
-l Optionsname,Optionsname,...Die Schreibweise
--longoptions Optionsname,Optionsname,...erfüllt den gleichen Zweck. Nicht im Manual angegeben, aber in Beispielen aus dem Internet findet man
--long Optionsname,Optionsname,...was auch funktioniert.
# # third-getopt-script.sh # set -- $(getopt -o ab:: -l size::,help -- $@) echo $@Das Script entspricht den Beispielen zuvor, hier aber erweitert um die Long-Options
size und help.
$ third-getopt-script.sh -b Hallo --help Welt -a --size -b '' --help -a --size '' -- 'Hallo' 'Welt'So unmöglich verteilt wird man Optionen und Argumente nicht angeben, aber
getopt sortiert alles
prima, links des Optionsstoppzeichens -- die Optionen, rechts davon die Argumente.-b und bei --size erwartet werden.
Da stehen jetzt leere Werte als Platzhalter.
$ third-getopt-script.sh -b25 --size88 getopt: unknown option -- size88 -b '25' --Da spielt
getopt jedoch nicht mit. Der Wert zur Kurzoption kommt einwandfrei an, aber --size88 wird als
unbekannte Option interpretiert.
$ third-getopt-script.sh -b25 --size 88 -b '25' --size '' -- '88'Auch kein Erfolg, jetzt wird die
88 als Argument verstanden, und --size
steht immer noch ein leerer Wert.$ third-getopt-script.sh -b25 --size=88 -b '25' --size '88' --Und jetzt klappt es tadellos,
--size hat den Wert erhalten.set -- $(getopt -l size::,help -- $@) # funktioniert nicht! echo $@
$ third-getopt-script.sh --size=88 --help Hallo Welt --help 'Hallo' 'Welt' --So ziemlich alles wird als Option interpretiert, und von
--size ist gar nichts zu sehen.man getopt) zeigt drei mögliche Syntaxschreibweisen:
getopt optstring parameters getopt [options] [--] optstring parameters getopt [options] -o|--options optstring [options] [--] parametersEs fällt auf, dass
optstring in allen drei Schreibweisen vorkommt.
Mit optstring ist die Angabe der gewünschten Kurzoptionen gemeint.
Nun ja, in unserem Beispiel wollten wir ja keine Kurzoptionen haben ...-o optstring angeben?
Probieren wir es mit einem leeren optstring:
set -- $(getopt -o '' -l size::,help -- $@) echo $@
$ third-getopt-script.sh --size=88 --help Hallo Welt --size '88' --help -- 'Hallo' 'Welt'Es sind keine Kurzoptionen definiert, alle Langoptionen und Argumente werden erkannt, korrekt sortiert, und auch der Wert für
--size ist da.-h eine Hilfe aus, aber auch bei --help.-h oder --help aus.
#
# fourth-getopt-script.sh
#
usage()
{
echo -e "\n"'Anwendung:
Das ist ein Demo des Kommandos "getopt"
Aufruf:
fourth-getopt-script.sh [Optionen]
Optionen:
-h|--help : gibt diese Hilfe aus
-s|--size : Ausgabe der Wertvorgabe
-sWert|--size=Wert : setzt den Wert
'"\n"; exit 0
}
# Wertvorgabe
SIZE=100
set -- $(getopt -o hs:: -l help,size:: -- $@)
while [ -n "$1" ]
do
case "$1" in
-h|--help)
shift; usage; break;
;;
-s|--size)
shift ; SW=$1 ; shift
if [ "$SW" == "''" ]
then
# Ausgabe der Wertvorgabe
echo "Vorgabe: $SIZE"
else
SIZE=$SW
# Auswertung des neuen Wert
echo "Wert ist jetzt $SIZE"
fi
;;
--) # Ende der Optionen
shift; break
;;
esac
done
echo "Ende des Scripts"
-h und --help denselben Zweck erfüllen,
nämlich eine Hife ausgeben.
Der Hilfetext steht in der Shellfunktion usage().case-Konstrukt sind daher beide Optionen im ersten Zweig angegeben, getrennt mit |:
-h|--help) # reagiert sowohl auf -h als auch auf --help
shift; usage; break;
;;
Dieses Zeichen ist ein ODER-Operator, je nachdem, welche der beiden Optionen eintritt,
erfolgt die geplante Reaktion.shift werden zuerst die Parameter geschoben, und usage, einfach so notiert,
ist der Aufruf
der Shellfunktion. Nun kann man überlegen, ob nach Ausgabe der Hilfe das Script weiterlaufen soll oder nicht.
Im Beispiel wurde ein break gesetzt, damit die while-Schleife verlassen und das Script
endet.-s und --size sollen Gleiches bewirken.
Hier wurde die Ausgabe eines vorgegebenen Wertes programmiert,
wenn die Optionen keinen Wert erhalten. Andernfalls wird der Wert ausgegeben.