getoptund getoptssind verschiedene Tiere, und die Leute scheinen ein bisschen Missverständnis darüber zu haben, was sie tun. getoptsist ein integrierter Befehl zum bashVerarbeiten von Befehlszeilenoptionen in einer Schleife und zum Zuweisen jeder gefundenen Option und jedes gefundenen Werts zu integrierten Variablen, damit Sie sie weiter verarbeiten können. getoptEs handelt sich jedoch um ein externes Dienstprogramm, das Ihre Optionen für Sie nicht so verarbeitet, wie es beispielsweise Bash getopts, das Perl- GetoptModul oder Python optparse/ argparseModule tun. Alles, getoptwas Sie tun müssen, ist, die übergebenen Optionen zu kanonisieren - dh sie in ein Standardformular zu konvertieren, damit ein Shell-Skript sie leichter verarbeiten kann. Beispielsweise kann eine Anwendung von getoptFolgendes konvertieren:
myscript -ab infile.txt -ooutfile.txt
das sehr gut finden:
myscript -a -b -o outfile.txt infile.txt
Sie müssen die eigentliche Bearbeitung selbst vornehmen. Sie müssen überhaupt nicht verwenden, getoptwenn Sie verschiedene Einschränkungen für die Angabe von Optionen vornehmen:
- Geben Sie nur eine Option pro Argument an.
- Alle Optionen stehen vor Positionsparametern (dh Argumenten ohne Option).
- Bei Optionen mit Werten (z. B.
-ooben) muss der Wert als separates Argument (nach einem Leerzeichen) angegeben werden.
Warum getoptstatt verwenden getopts? Der Hauptgrund ist, dass nur GNU getoptIhnen Unterstützung für lange benannte Befehlszeilenoptionen bietet. 1 (GNU getoptist die Standardeinstellung unter Linux. Mac OS X und FreeBSD werden mit einer einfachen und nicht sehr nützlichen Version geliefertgetopt Version , aber die GNU-Version kann installiert werden. Siehe unten.)
Hier ist zum Beispiel ein Beispiel für die Verwendung von GNU getoptaus einem meiner Skripte mit dem Namen javawrap:
# NOTE: This requires GNU getopt. On Mac OS X and FreeBSD, you have to install this
# separately; see below.
TEMP=`getopt -o vdm: --long verbose,debug,memory:,debugfile:,minheap:,maxheap: \
-n 'javawrap' -- "$@"`
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
# Note the quotes around `$TEMP': they are essential!
eval set -- "$TEMP"
VERBOSE=false
DEBUG=false
MEMORY=
DEBUGFILE=
JAVA_MISC_OPT=
while true; do
case "$1" in
-v | --verbose ) VERBOSE=true; shift ;;
-d | --debug ) DEBUG=true; shift ;;
-m | --memory ) MEMORY="$2"; shift 2 ;;
--debugfile ) DEBUGFILE="$2"; shift 2 ;;
--minheap )
JAVA_MISC_OPT="$JAVA_MISC_OPT -XX:MinHeapFreeRatio=$2"; shift 2 ;;
--maxheap )
JAVA_MISC_OPT="$JAVA_MISC_OPT -XX:MaxHeapFreeRatio=$2"; shift 2 ;;
-- ) shift; break ;;
* ) break ;;
esac
done
Auf diese Weise können Sie Optionen wie --verbose -dm4096 --minh=20 --maxhe 40 --debugfi="/Users/John Johnson/debug.txt"oder ähnlich angeben . Der Aufruf von getoptbesteht darin, die Optionen zu kanonisieren, --verbose -d -m 4096 --minheap 20 --maxheap 40 --debugfile "/Users/John Johnson/debug.txt"damit Sie sie einfacher verarbeiten können. Das Zitieren um "$1"und "$2"ist wichtig, da es sicherstellt, dass Argumente mit Leerzeichen richtig behandelt werden.
Wenn Sie die ersten 9 Zeilen löschen (alles durch die eval setZeile), funktioniert der Code weiterhin ! Ihr Code ist jedoch viel wählerischer in Bezug auf die Arten von Optionen, die er akzeptiert: Insbesondere müssen Sie alle Optionen in der oben beschriebenen "kanonischen" Form angeben. Mit der Verwendung von getoptkönnen Sie jedoch Einzelbuchstabenoptionen gruppieren, kürzere, nicht mehrdeutige Formen von Langoptionen verwenden, entweder den --file foo.txtoder --file=foo.txt-Stil verwenden, entweder den -m 4096oder -m4096-Stil verwenden, Optionen und Nichtoptionen in beliebiger Reihenfolge mischen usw. getopt gibt auch eine Fehlermeldung aus, wenn nicht erkannte oder mehrdeutige Optionen gefunden werden.
HINWEIS : Es gibt tatsächlich zwei völlig unterschiedliche Versionen von getoptBasic getoptund GNU getoptmit unterschiedlichen Funktionen und unterschiedlichen Anrufkonventionen. 2 Basic getoptist ziemlich kaputt: Es verarbeitet nicht nur keine langen Optionen, sondern auch nicht einmal eingebettete Leerzeichen innerhalb von Argumenten oder leeren Argumenten, wohingegen getoptsdies richtig ist. Der obige Code funktioniert nicht in Basic getopt. GNU getoptwird standardmäßig unter Linux installiert, muss jedoch unter Mac OS X und FreeBSD separat installiert werden. Installieren Sie unter Mac OS X MacPorts ( http://www.macports.org ) und sudo port install getoptinstallieren Sie dann GNU getopt(normalerweise in /opt/local/bin) und stellen Sie sicher, dass /opt/local/binsich das in Ihrem Shell-Pfad befindet/usr/bin. Installieren Sie unter FreeBSD misc/getopt.
Eine Kurzanleitung zum Ändern des Beispielcodes für Ihr eigenes Programm: Von den ersten Zeilen ist alles "Boilerplate", das bis auf die aufrufende Zeile gleich bleiben sollte getopt. Sie sollten den Programmnamen nach ändern -n, kurze Optionen nach -ound lange Optionen nach angeben --long. Setzen Sie nach Optionen, die einen Wert annehmen, einen Doppelpunkt.
Wenn Sie schließlich Code sehen, der nur setanstelle von hat eval set, wurde er für BSD geschrieben getopt. Sie sollten es ändern, um den eval setStil zu verwenden, der mit beiden Versionen von gut funktioniert getopt, während die Ebene setmit GNU nicht richtig funktioniert getopt.
1 Eigentlich getoptsin ksh93Trägern lange genannte Optionen, aber diese Schale nicht so oft verwendet bash. In zshVerwenden Sie zparseoptsdiese Funktionalität zu erhalten.
2 Technisch gesehen ist "GNU getopt" eine Fehlbezeichnung. Diese Version wurde eher für Linux als für das GNU-Projekt geschrieben. Es folgt jedoch allen GNU-Konventionen, und der Begriff "GNU getopt" wird häufig verwendet (z. B. bei FreeBSD).