Warum können Leerzeichen zwischen Optionen und Parametern weggelassen werden?

16

Beispielsweise:

xargs -n 1

ist das gleiche wie

xargs -n1

Wenn Sie sich jedoch die Manpage ansehen , wird die Option als aufgeführt -n max-args, was bedeutet, dass der Speicherplatz beibehalten werden soll. Es gibt nichts über die abgekürzte Form -n max-args .

Dies ist auch bei vielen anderen Linux-Dienstprogrammen der Fall.

Wie heißt das unter Linux? Unterstützen alle Dienstprogramme das abgekürzte Formular (aber dokumentieren Sie es niemals in der Manpage)?

J.Joe
quelle
1
12.1.2.a ist ein Teil der Geschichte; Ich schwöre, es gibt hier schon eine gute Frage, aber ich habe sie noch nicht gefunden.
2
@ Drewbenn Die andere Frage, an die Sie denken, könnte meine gewesen sein: unix.stackexchange.com/q/188046/41515

Antworten:

12

Wenn Sie das Befehlszeilen-Parsing-Bit Ihres Codes schreiben, geben Sie an, welche Optionen Argumente annehmen und welche nicht. Beispiel: In einem Shell-Skript akzeptieren Sie eine -hOption (z. B. Hilfe) und eine -aOption, die ein Argument enthalten soll

opt_h=0     # default value
opt_a=""

while getopts 'a:h' opt; do
    case $opt in
        h)  opt_h=1 ;;
        a)  opt_a="$OPTARG" ;;
    esac
done

echo "h: $opt_h"
echo "a: $opt_a"

Das a:hBit sagt "Ich erwarte, zwei Optionen zu analysieren, -aund -h, und -asollte ein Argument nehmen" (es ist das :After a, das dem Parser sagt, dass es -aein Argument nimmt).

Daher gibt es keine Unklarheit, wo eine Option endet, wo ihr Wert beginnt und wo eine andere danach beginnt.

Laufen es:

$ bash test.sh -h -a hello
h: 1
a: hello

$ bash test.sh -h -ahello
h: 1
a: hello

$ bash test.sh -hahello
h: 1
a: hello

Aus diesem Grund sollten Sie die meiste Zeit keinen eigenen Befehlszeilenparser schreiben, um Optionen zu analysieren.

In diesem Beispiel gibt es nur einen Fall, der schwierig ist. Das Parsen stoppt normalerweise bei der ersten Nicht-Option. Wenn Sie also Dinge in der Befehlszeile haben, die wie Optionen aussehen :

$ bash test.sh -a hello -world
test.sh: illegal option -- w
test.sh: illegal option -- o
test.sh: illegal option -- r
test.sh: illegal option -- l
test.sh: illegal option -- d
h: 0
a: hello

Das Folgende löst das:

$ bash test.sh -a hello -- -world
h: 0
a: hello

Das --signalisiert ein Ende der Befehlszeilenoptionen, und das -worldBit bleibt dem Programm übrig, um zu tun, was es will (es befindet sich in einer der Positionsvariablen).

Das ist übrigens, wie Sie eine Datei entfernen, die einen Bindestrich am Anfang ihres Dateinamens mit hat rm.

EDIT :

In C aufgerufene getopt()(in deklarierte unistd.h) Dienstprogramme, die auf die gleiche Weise funktionieren. Soweit wir wissen, kann die bashFunktion getoptstatsächlich unter Verwendung eines Aufrufs der C-Bibliotheksfunktion implementiert werden getopt(). Perl, Python und andere Sprachen verfügen über ähnliche Befehlszeilen-Analysebibliotheken, und es ist sehr wahrscheinlich, dass sie ihre Analyse auf ähnliche Weise durchführen.

Einige dieser getoptund getoptähnliche Bibliotheksroutinen verarbeiten auch "lange" Optionen. Vor diesen steht normalerweise double-dash ( --), und lange Optionen, die Argumente enthalten, werden häufig nach einem Gleichheitszeichen angegeben, z. B. die --block-size=SIZEOption [einiger Implementierungen] des duDienstprogramms (mit der auch -B SIZEdasselbe angegeben werden kann).

Die Grundhandbücher werden oft geschrieben, um ein Leerzeichen zwischen den kurzen Optionen anzuzeigen, und ihre Argumente dienen wahrscheinlich der Lesbarkeit.

BEARBEITEN : Wirklich alte Werkzeuge, wie die ddund tarDienstprogramme, haben Optionen ohne Bindestriche vor sich. Dies geschieht ausschließlich aus historischen Gründen und um die Kompatibilität mit Software aufrechtzuerhalten, die darauf angewiesen ist, dass sie genau so funktioniert. Das tarDienstprogramm hat in jüngster Zeit die Möglichkeit erhalten, Optionen mit Bindestrichen zu verwenden. Das BSD-Handbuch für tarruft die alten Optionen für "gebündelte Flags" auf.

Kusalananda
quelle
Diese Funktion scheint in Bash-Skripten einfach zu implementieren zu sein. Aber ich denke, die meisten Dienstprogramme sind in C geschrieben (dann in Binärdateien kompiliert) und nicht in bash. Warum implementieren diese Dienstprogramme diese Funktion?
J. Joe
@ J.Joe Weil sie anrufen getopt()(deklariert in unistd.h), was dasselbe macht.
Kusalananda
2
Ja, du hast recht. Referenz . Dies löst auch ein weiteres Rätsel, dass Optionen kombiniert werden können -a -b=== -ab
J.Joe
1
Optionale Argumente für Flags würden eine Mehrdeutigkeit erzeugen, sodass sie nicht kombiniert werden können (wenn -aoptionales Argument vorhanden ist, -abist dies nicht dasselbe wie -a -b). GNU getopt stoppt die Verarbeitung von Flags nicht, wenn ein Nicht-Flag gefunden wird: Stattdessen (standardmäßig) werden die Flags vor argv neu gemischt.
Ilkkachu
@ilkkachu Danke für die Klarstellung. Ich kann meine Antwort später aktualisieren.
Kusalananda
4

xargsist eines der POSIX-Dienstprogramme. Wie von @drewbenn kommentiert, dokumentiert POSIX das Verhalten beim Analysieren von Optionen, damit die meisten seiner Dienstprogramme übereinstimmen getopt, mit einigen Zulassungen für andere Implementierungen. In 12.1 Utility Argument Syntax heißt es :

In diesem Abschnitt wird die Argumentensyntax der Standarddienstprogramme beschrieben und die in POSIX.1-2008 verwendete Terminologie zur Beschreibung der von den Dienstprogrammen verarbeiteten Argumente eingeführt.

In POSIX.1-2008 wird eine spezielle Notation verwendet, um die Syntax der Argumente eines Dienstprogramms zu beschreiben. Sofern nicht anders angegeben , verwenden alle Dienstprogrammbeschreibungen diese Notation, die in diesem Beispiel veranschaulicht wird (siehe XCU Simple Commands ):

und abschließend mit

Es wird empfohlen, dass alle zukünftigen Dienstprogramme und Anwendungen diese Richtlinien verwenden, um die Portabilität der Benutzer zu verbessern. Die Tatsache, dass einige historische Dienstprogramme nicht geändert werden konnten (um zu vermeiden, dass vorhandene Anwendungen beschädigt werden), sollte dieses zukünftige Ziel nicht abschrecken.

In POSIX (denken Sie daran, dass es nur die am häufigsten verwendeten Dienstprogramme abdeckt) gibt es Ausnahmen, die Operanden übergeben, die Optionen in anderen Dienstprogrammen sind, entweder als Positionsparameter oder als Parameter mit spezieller Syntax :

POSIX erlaubt optionale Optionswerte:

Optionsargumente werden durch <blank>Zeichen von ihren Optionen getrennt angezeigt , außer wenn das Optionsargument in der '['und ']'-Notation eingeschlossen ist, um anzuzeigen, dass es optional ist.

Ich kann mich nicht erinnern, welche POSIX-Dienstprogramme diese Funktion verwenden. Die ncurses ticund infocmpDienstprogramme verwenden die Funktion für Ebenen der -vOption (verbose / debug).

Der spezielle Punkt, nach dem Sie gefragt haben, wird im Rest dieses Absatzes in mehreren Zeilen beschrieben.

Vor POSIX einige Implementierungen psakzeptierter Optionen ohne führenden Bindestrich. In der POSIX-Beschreibung wird Folgendes in der Beschreibung des Dienstprogramms oder in der Syntaxbegründung nicht erwähnt:

Abgesehen von POSIX gibt es Implementierungen mit langen Optionen (wie GNU getopt_long oder X Toolkit ), bei denen auf verschiedene Arten der Wert einer Option von der Option getrennt oder mit ihr verknüpft wird . Beispielsweise kann Interpunktion verwendet werden:

--option=value
--option value

Abhängig von der Implementierung kann ein doppelter Gedankenstrich verwendet werden, um lange Optionen von kurzen zu unterscheiden (getopt): lynx und X Toolkit verwenden einen einzelnen Gedankenstrich; GNU getopt_longverwendet zum Beispiel einen Doppelstrich. A +kann auch verwendet werden, um anzuzeigen, dass eine Option negiert ist.

In der Beschreibung von POSIX werden diese offenbar nicht erwähnt, aber Sie werden ihnen mit Sicherheit begegnen.

Thomas Dickey
quelle
Soll -option=valuees sein --option=value? (Das Long-Option-Format, zwei Striche am Anfang anstelle von einem)
J.Joe
Einige ältere Dienstprogramme verwenden Single-Dash-Long-Optionen (-Option), sind jedoch für neue Skripte und Programme weitgehend veraltet. Verwenden Sie einen einfachen Gedankenstrich für kurze Optionen, wie sie von getopt behandelt werden. Fast alle neuen Skripte und Programme verwenden lange Optionen mit Doppelstrichen. Viele unterstützen auch Äquivalente für Single-Dash-Short-Optionen für die am häufigsten verwendeten. Durch lange Optionen ist der Skriptcode weitaus selbstdokumentierender und benötigt weniger Kommentare.
DocSalvager