getopt
y getopts
sind unterschiedliche Wesen, und die Menschen scheinen ihre Aufgaben nicht richtig zu verstehen. getopts
ist ein eingebauter Befehl zur bash
um Befehlszeilenoptionen in einer Schleife zu verarbeiten und jede gefundene Option und jeden gefundenen Wert der Reihe nach eingebauten Variablen zuzuweisen, damit Sie sie weiter verarbeiten können. getopt
ist jedoch ein externes Hilfsprogramm, und es nicht wirklich Ihre Optionen für Sie bearbeitet die Art und Weise, wie z.B. bash getopts
die Perl Getopt
Modul oder das Python optparse
/ argparse
Module tun. All das getopt
ist es, die übergebenen Optionen zu kanonisieren - d.h. sie in eine Standardform umzuwandeln, so dass es für ein Shell-Skript einfacher ist, sie zu verarbeiten. Zum Beispiel kann eine Anwendung von getopt
könnte das Folgende umwandeln:
myscript -ab infile.txt -ooutfile.txt
in diese:
myscript -a -b -o outfile.txt infile.txt
Die eigentliche Bearbeitung müssen Sie selbst vornehmen. Sie müssen nicht getopt
überhaupt nicht, wenn Sie verschiedene Einschränkungen bei der Angabe von Optionen vornehmen:
- nur eine Option pro Argument angeben;
- alle Optionen stehen vor allen Positionsparametern (d.h. Nicht-Options-Argumenten);
- für Optionen mit Werten (z. B.
-o
oben), muss der Wert als separates Argument (nach einem Leerzeichen) angegeben werden.
Warum verwenden getopt
代わりに getopts
? Der Hauptgrund ist, dass nur GNU getopt
bietet Ihnen Unterstützung für lang benannte Befehlszeilenoptionen. 1 (GNU getopt
ist die Standardeinstellung unter Linux. Mac OS X und FreeBSD werden mit einem einfachen und nicht sehr nützlichen getopt
aber die GNU-Version kann installiert werden; siehe unten).
Hier zum Beispiel ein Beispiel für die Verwendung von GNU getopt
aus einem Skript von mir namens 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 angeben wie --verbose -dm4096 --minh=20 --maxhe 40 --debugfi="/Users/John Johnson/debug.txt"
oder ähnlich. Die Wirkung des Aufrufs zu getopt
ist die Kanonisierung der Optionen auf --verbose -d -m 4096 --minheap 20 --maxheap 40 --debugfile "/Users/John Johnson/debug.txt"
damit Sie sie leichter bearbeiten können. Die Quotierung um "$1"
y "$2"
ist wichtig, da sie sicherstellt, dass Argumente mit Leerzeichen richtig behandelt werden.
Wenn Sie die ersten 9 Zeilen löschen (alles bis zur eval set
Zeile), wird der Code noch funktionieren ! Allerdings wird Ihr Code viel wählerischer sein, was die akzeptierten Optionen angeht: Insbesondere müssen Sie alle Optionen in der oben beschriebenen "kanonischen" Form angeben. Mit der Verwendung von getopt
können Sie jedoch Optionen mit einzelnen Buchstaben gruppieren, kürzere, nicht eindeutige Formen von langen Optionen verwenden, entweder die --file foo.txt
o --file=foo.txt
Stil, verwenden Sie entweder die -m 4096
o -m4096
Stil, Mischung von Optionen und Nicht-Optionen in beliebiger Reihenfolge, usw. getopt
gibt auch eine Fehlermeldung aus, wenn nicht erkannte oder mehrdeutige Optionen gefunden werden.
ANMERKUNG : Es gibt eigentlich zwei völlig unterschiedlich Versionen von getopt
, grundlegend getopt
und GNU getopt
mit unterschiedlichen Funktionen und unterschiedlichen Anrufkonventionen. 2 Grundlegend getopt
ist ziemlich kaputt: Er kann nicht nur keine langen Optionen verarbeiten, sondern auch keine eingebetteten Leerzeichen innerhalb von Argumenten oder leere Argumente, während getopts
macht das richtig. Der obige Code wird in Basic nicht funktionieren getopt
. GNU getopt
ist unter Linux standardmäßig installiert, unter Mac OS X und FreeBSD muss es jedoch separat installiert werden. Unter Mac OS X installieren Sie MacPorts ( http://www.macports.org ) und tun dann sudo port install getopt
zur Installation von GNU getopt
(normalerweise in /opt/local/bin
), und stellen Sie sicher, dass /opt/local/bin
ist in Ihrem Shell-Pfad vor /usr/bin
. Unter FreeBSD installieren Sie misc/getopt
.
Eine Kurzanleitung zum Ändern des Beispielcodes für Ihr eigenes Programm: Die ersten paar Zeilen sind allesamt "Standardtexte", die unverändert bleiben sollten, mit Ausnahme der Zeile, die Folgendes aufruft getopt
. Sie sollten den Programmnamen ändern, nachdem Sie -n
geben Sie kurze Optionen nach -o
und lange Optionen nach --long
. Setzen Sie einen Doppelpunkt nach Optionen, die einen Wert annehmen.
Schließlich, wenn Sie Code sehen, der gerade set
代わりに eval set
Es wurde für BSD geschrieben. getopt
. Sie sollten es so ändern, dass Sie die eval set
Stil, der mit beiden Versionen von getopt
, während die Ebene set
funktioniert nicht richtig mit GNU getopt
.
1 Eigentlich, getopts
en ksh93
unterstützt lang benannte Optionen, aber diese Shell wird nicht so oft benutzt wie bash
. Unter zsh
verwenden zparseopts
um diese Funktionalität zu erhalten.
2 Technisch gesehen, "GNU getopt
" ist eine falsche Bezeichnung; diese Version wurde eigentlich für Linux und nicht für das GNU-Projekt geschrieben. Sie folgt jedoch allen GNU-Konventionen, und der Begriff "GNU getopt
" wird üblicherweise verwendet (z.B. unter FreeBSD).