Wie kann ich feststellen, dass bei getopts keine Optionen übergeben wurden?

19

Ich habe diesen Code -

#getoptDemo.sh
usage()
{
    echo "usage: <command> options:<w|l|h>"
}
while getopts wlh: option
do
    case $option in
            (w)
                    name='1';;
            (l)
                    name='2';;
            (h)
                    name='3';;
            (*)
                    usage
                    exit;;
    esac
done
print 'hi'$name

Beim Ausführen bash getoptDemos.sh(ohne die Option) wird gedruckt, hianstatt die Funktion aufzurufen usage. Es ruft die Verwendung auf, wenn andere Optionen als w, h und l angegeben werden. Dann kann es nicht funktionieren, wenn keine Optionen angegeben sind.

Ich habe versucht , mit ?, \?, :anstatt *aber ich kann nicht erreichen , was ich wollte. Ich meine alles docsauf , getoptsagt , es zu benutzen ?.

Was mache ich falsch?

Hussain Tamboli
quelle
Unter welcher Shell läuft es?
Julian
Ich /bin/bash
leite

Antworten:

15

Wenn Sie dieses Skript ohne Optionen ausführen, gibt getopt false zurück, sodass es überhaupt nicht in die Schleife eintritt. Es wird nur auf den Ausdruck fallen - ist das ksh / zsh?

Wenn Sie eine Option benötigen, sollten Sie $ name nach der Schleife testen.

if [ -z "$name" ]
then
   usage
   exit
fi

Stellen Sie jedoch sicher, dass $namevor dem Aufruf leer war getopts(da es $namein der Umgebung möglicherweise ein Shell-Element gab, das beim Start empfangen wurde)

unset name

(vor der getoptsSchleife)

julianisch
quelle
Nein. es ist bash. Also, wie erreiche ich, was ich will - die no argumentBedingung mit Bash behandeln.
Hussain Tamboli
Wenn Sie eine obligatorische Option wünschen, denke ich nicht, dass dies möglich ist - wahrscheinlich werden sie deshalb Optionen genannt :) Sie können $ name jedoch nach der Schleife testen, um sicherzustellen, dass es festgelegt wurde. if [-z "$ name"]; dann Nutzung; Ausfahrt ; fi
Julian
Vielen Dank. Der obige Code hat wirklich geholfen. Es ist schade, getoptshat keine solche Bestimmung. Was schlimmer als das ist, kann dich nicht unterstützen.
Hussain Tamboli
Was wäre, wenn ich eine andere Shell laufen würde? zsh, sh. kümmert sich eine andere Shell als bash um diesen Zustand?
Hussain Tamboli
20

getoptsverarbeitet die Optionen der Reihe nach. Das ist seine Aufgabe. Wenn der Benutzer keine Option übergibt, getoptsverlässt der erste Aufruf von die while-Schleife.

Wenn keine der Optionen ein Argument akzeptiert, gibt der Wert von OPTINDan, wie viele Optionen übergeben wurden. Im Allgemeinen OPTINDist dies die Anzahl der Argumente, die Optionen oder Argumente für Optionen sind, im Gegensatz zu Nichtoptionsargumenten (Operanden).

while getopts …; do …; done
if [ $OPTIND -eq 1 ]; then echo "No options were passed"; fi
shift $((OPTIND-1))
echo "$# non-option arguments"

In jedem Fall versuchen Sie nicht festzustellen, ob es keine Optionen gab, sondern ob keine der name-setting-Optionen übergeben wurde. Überprüfen Siename daher , ob die Einstellung deaktiviert ist (und achten Sie darauf, sie zuerst zu deaktivieren) .

Gilles 'SO - hör auf böse zu sein'
quelle
1
Vielen Dank. +1 für dich. wenn ich die letzten 3 zeilen aus deinem code in sample.sh stecke und es ausführe bash sample.sh -abc file.txtgibt es - 1 non-option arguments. Wie finde ich heraus, wie viele Optionen gegeben wurden? (hier 3)
Hussain Tamboli
1
Seltsamerweise hat niemand diesen kleinen Fehler kommentiert - wenn keine Optionen angegeben sind, wird OPTIND nach dieser 'while getopts ...'-Schleife 1 sein. Daher sollte die if-Prüfung die Gleichheit mit 1 und nicht mit Null prüfen.
Daniel
4

Wenn Ihr Skript Optionsargumente erhalten muss, setzen Sie diesen Block an den Anfang (vor getops).

if [[ ! $@ =~ ^\-.+ ]]
then
  #display_help;
fi

Block prüft, ob die Parameterzeichenfolge nicht mit dem -Symbol beginnt . Dies zeigt an, dass der erste Parameter kein Optionsargument ist.

mcounad
quelle
2

Ich würde es mit einer Variablen überprüfen. Wenn getopts die Schleife niemals ohne Argument passiert, können Sie das zum Beispiel so verwenden:

#getoptDemo.sh
usage()
{
    echo "usage: <command> options:<w|l|h>"
}

no_args="true"
while getopts wlh: option
do
    case $option in
            (w)
                    name='1';;
            (l)
                    name='2';;
            (h)
                    name='3';;
            (*)
                    usage
                    exit;;
    esac
    no_args="false"
done

[[ "$no_args" == "true" ]] && { usage; exit 1; }

print 'hi'$name
Imre Kneifel
quelle
0

getoptsÜberprüfen Sie kurz vor Ihrem Block, ob $1(das erste Argument / die erste Option, die Sie in der Befehlszeile übergeben haben) einer leeren Zeichenfolge entspricht. Wenn dies der Fall ist, drucken Sie die Verwendungsmeldung aus und beenden Sie das Programm (oder führen Sie eine Funktion ohne Optionen aus, wenn Sie ein Anarchist sind). Anderenfalls lassen Sie getoptsdie Optionen wie gewohnt analysieren.

Der Grund, warum diese Funktion nicht in getopts enthalten ist, ist, dass Sie sie bereits mit einem "if-else" ausführen können. Beispiel:

if [[ $1 == "" ]]; then
    Your_Usage_Function;
    exit;
else
   #parse options with getopts code block here;
fi

Sinn ergeben?

codrcodz
quelle