2014-10-17 5 views
6

Wenn Sie getopt verwenden, um Kommandozeilenparameter zu analysieren, können Sie ein Leerzeichen zwischen dem Optionsflag und dem Argument für erforderliche Argumente setzen, nicht jedoch für optionale Argumente. Optionale Argumente werden nur analysiert, wenn sie direkt hinter der Option stehen.Warum kann ich ein Leerzeichen zwischen Option und optionalem Argument mit getopt nicht haben?

TEMP=`getopt -o p:q:: -n 'mkqueue.sh' -- "[email protected]"` 

if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi 

# Note the quotes around `$TEMP': they are essential! 
eval set -- "$TEMP" 

# Now go through all the options 
while true ; do 
    case "$1" in 
     -p) echo "Option p, argument \`$2'" ; shift 2 ;; 
     -q) 
      case "$2" in 
       "") echo "Option q, no argument"; shift 2 ;; 
       *) echo "Option q, argument \`$2'" ; shift 2 ;; 
      esac ;; 
     --) shift ; break ;; 
     *) echo "Internal error!" ; exit 1 ;; 
    esac 
done 

(Auf dieser Basis: http://software.frodo.looijaard.name/getopt/docs/getopt-parse.bash)

Als ich das Skript ohne das optionale Argument funktioniert es:

./mkqueue.sh -p adfsa -q 
Option p, argument `adfsa' 
Option q, no argument 

Wenn ich versuche, das optionale Argument hinzuzufügen, mit einem -q Platz dazwischen Es funktioniert nicht:

./mkqueue.sh -p adfsa -q sdfasdfa 
Option p, argument `adfsa' 
Option q, no argument 

Es funktioniert, wenn Sie nicht als haben Tempo zwischen Option und Argument, obwohl die erforderlichen Argumente mit dem Leerzeichen arbeiten:

./mkqueue.sh -p adfsa -qsdfasdfa 
Option p, argument `adfsa' 
Option q, argument `sdfasdfa' 

Gibt es eine Lösung dafür?

+2

Wenn es erlaubt wäre, würden Sie ein anderes Problem bekommen. Angenommen, Ihr Programm akzeptiert auch ein Positionsargument. Sollte './a.out -q foo bar' als' ./a.out -qfoo bar' oder als './a.out -q - foo bar' geparst werden? – 5gon12eder

+1

@ 5gon12eder, wenn du das als Antwort hättest, hättest du zumindest meinen upvote. Es erklärt das "Warum", was der Titel dieser Frage verlangt. :) –

Antwort

8

Diese Beschränkung in der Manpage getopt dokumentiert ist:

Eine einfache kurze Option ist ein `-‘ durch eine kurze Option Zeichen folgt. Wenn die Option ein erforderliches Argument hat, kann sie direkt nach dem Optionszeichen oder als nächster Parameter geschrieben werden (dh durch Leerzeichen in der Befehlszeile getrennt). Wenn die Option ein optionales Argument hat, muss sie direkt nach dem Optionszeichen geschrieben werden, falls vorhanden.

Obwohl getopt „optional Option Argumente“ ermöglicht, sind sie in der Regel eine schlechte Idee zu sein betrachtet. Die Posix Utility Syntax Guidelines zum Beispiel umfasst:

Leitlinie 7: Option-Argumente sollten nicht optional sein.

Der Grund für diese Richtlinie ist, dass das Argument einer Befehlszeilenoption per Konvention beliebig sein kann. Es könnte zum Beispiel wie eine andere Option aussehen. Es könnte die Literalzeichenfolge -- sein, die normalerweise das Ende der Optionsliste angibt. Es könnte eine leere Zeichenfolge sein. Etwas.

Das Problem mit "optionalen Optionsargumenten" ist, dass die einzige Möglichkeit zu wissen, dass ein optionales Optionsargument nicht bereitgestellt wird, das folgende Argument als eine Option oder -- erkennen. Das bedeutet jedoch, dass der Wert des optionalen Arguments nicht mit - beginnen kann.

Alternativ können Sie die vom Befehlszeilenprogramm getopt übernommene Lösung auswählen, die erfordert, dass das optionale Argument direkt der Option folgt, ohne Leerzeichen dazwischen (dh im selben Wort). In diesem Fall darf das optionale Argument jedoch keine leere Zeichenfolge sein.

Anstatt komplizierte Regeln zur Lösung dieser Mehrdeutigkeiten zu erstellen, ist die einfache Lösung - empfohlen von Posix (und mit sehr viel weniger Autorität von mir) - Optionsargumente nicht optional zu sein.Wenn es für eine Befehlszeilenoption einen gemeinsamen Wert gibt und Sie das Leben des Benutzers vereinfachen möchten, indem Sie nicht angeben müssen, dass es eingegeben werden soll, implementieren Sie zwei verschiedene Befehlszeilenoptionen, von denen die eine ein Argument und die andere davon akzeptiert nicht. Zu den gebräuchlichen Techniken gehören die Verwendung eines Kleinbuchstabens für die Version ohne ein Argument und das entsprechende Großbuchstabe für die Version mit einem Argument oder die Verwendung einer langen Option (--option) für diese Version.

Für diejenigen, die dicht und verpackte Erklärung bevorzugen, die Posix rationale erklärt, dass:

Leitlinie 7 ermöglicht eine beliebige Zeichenfolge ein Option-Argument zu sein; Ein option-Argument kann mit einem beliebigen Zeichen beginnen, kann oder -- sein und kann eine leere Zeichenfolge sein. Zum Beispiel können die Befehle pr -h -, pr -h --, pr -h -d, pr -h +2 und pr -h '' enthalten die Optionsargumente -, --, -d, +2, und ein leerer String, respectively. Umgekehrt behandelt der Befehl pr -h -- -d -d als Option, nicht als Argument, da -- hier ein option-Argument ist, kein Trennzeichen.

+0

Es ist eine gute Erklärung und vollständig, aber ich denke ein wenig dicht. Es mag hilfreich sein, die Beispiele der Rationale ein wenig auszupacken (nicht jeder weiß, was '' bedeutet, z. B.). –

Verwandte Themen