Warum gibt es in Shell-Schleifen kein ;
Zeichen danach, do
wenn es in eine einzelne Zeile geschrieben wird?
Hier ist was ich meine. In mehreren Zeilen for
sieht eine Schleife folgendermaßen aus:
$ for i in $(jot 2)
> do
> echo $i
> done
Und in einer einzigen Zeile:
$ for i in $(jot 2); do echo $i; done
Alle die kollabierte Linien erhalten eine ;
nach ihnen , außer für die do
Linie, und wenn Sie das sind ;
, ist es ein Fehler. Jemand, der wahrscheinlich viel schlauer ist als ich, hat entschieden, dass dies aus einem bestimmten Grund richtig ist, aber ich kann den Grund nicht herausfinden. Es scheint mir widersprüchlich.
Das gleiche gilt auch für while
Schleifen.
$ while something
> do
> anotherthing
> done
$ while something; do anotherthing; done
while
/for
.Antworten:
Das ist die Syntax des Befehls. Siehe Zusammengesetzte Befehle
Beachten Sie insbesondere:
do commands
Die meisten Leute setzen das
do
undcommands
in eine separate Zeile, um die Lesbarkeit zu verbessern. Es ist jedoch nicht erforderlich, dass Sie Folgendes schreiben:Ich weiß, dass es sich bei dieser Frage speziell um Shell handelt und ich habe auf das Bash-Handbuch verwiesen. Es ist nicht so im Shell-Handbuch geschrieben, aber es ist so in einem Artikel von Stephen Bourne für das Byte-Magazin geschrieben.
Stephen sagt:
quelle
for i in thing; do; something; done
. Obwohl ein Zeilenumbruch zulässig ist, ist ein Semikolon nicht zulässig.something
ist das Thema unddo
gilt dafür. Genau wie in der englischen Satzstruktur.while
Syntax) mehrere Befehle enthalten sein können. Sie müssen also etwas tun, um die Bedingungsbefehle von den Schleifenhauptteilbefehlen zu unterscheiden. Das Verwendendo
, um sie zu trennen, schien wahrscheinlich am besten zu passen.Ich weiß nicht, was der ursprüngliche Grund für diese Syntax ist, aber betrachten wir die Tatsache, dass
while
Schleifen im Bedingungsabschnitt mehrere Befehle annehmen können, zHier ist das
do
Schlüsselwort erforderlich, um den Bedingungsabschnitt und den Hauptkörper der Schleife voneinander zu unterscheiden.do
ist ein Schlüsselwort wiewhile
,if
undthen
(unddone
), und es scheint , mit den anderen in Einklang zu sein , dass es nicht ein Semikolon oder Newline , nachdem es erfordert , sondern unmittelbar vor einem Befehl erscheint.Die Alternative (verallgemeinert auf
if
undwhile
) würde etwas hässlich aussehen, wir müssten zB schreibenDie Syntax von
for
Schleifen ist ähnlich.quelle
Die Shell-Syntax basiert auf einem Präfix. Es enthält Klauseln, die durch spezielle Schlüsselwörter eingeführt werden. Bestimmte Klauseln müssen zusammenpassen.
Eine
while
Schleife besteht aus einem oder mehreren Testbefehlen:und durch einen oder mehrere Körperbefehle:
Etwas muss der Shell mitteilen, dass eine while-Schleife beginnt. Das ist der Zweck des
while
Wortes:Aber dann sind die Dinge nicht eindeutig. Welcher Befehl ist der Beginn des Körpers? Etwas muss darauf hinweisen, und das macht das
do
Präfix:und schließlich muss etwas darauf hindeuten, dass der letzte Körper gesehen wurde; ein spezielles Schlüsselwort
done
macht das.Diese Shell-Schlüsselwörter erfordern keine Semikolon-Trennung, auch nicht in derselben Zeile. Wenn Sie beispielsweise mehrere verschachtelte Schleifen schließen, können Sie nur haben
done done done ...
.Das Semikolon steht vielmehr zwischen,
... test ; body ...
wenn sie sich in derselben Zeile befinden. Das Semikolon wird als Terminator verstanden: Es gehört zumtest
. Wenn eindo
Schlüsselwort dazwischen eingefügt wird, muss es daher zwischen dem Semikolon und stehenbody
. Wenn es sich auf der anderen Seite des Semikolons befindet, wird es fälschlicherweise in dietest
Befehlssyntax eingebettet und nicht zwischen den Befehlen platziert.Die Shell-Syntax wurde ursprünglich von Stephen Bourne entworfen und ist von Algol inspiriert . Borowski liebte Algol so sehr, dass er viele C-Makros im Shell-Quellcode verwendete, um C wie Algol aussehen zu lassen. Sie können die Shell-Quellen von 1979 ab Version 7 Unix durchsuchen . Die Makros sind in
mac.h
und sie werden überall verwendet. Beispielsweise werdenif
Aussagen alsIF
...ELSE
...ELIF
... wiedergegebenFI
.quelle
Ich würde behaupten, dass das
do
hier nicht besonders speziell ist. Sie erhalten eine Fehlermeldung, weil;
keine Befehlsliste gestartet werden kann. In diesem Fall wäre der erste Befehl leer, und die Grammatik lässt keine leeren Befehle zu (Variablenzuweisungen oder -umleitungen ohne Befehl, ja, aber absolut nichts, nein). Dies gilt an beliebig vielen Stellen, an denen eine Liste von Befehlen erwartet wird:Sogar:
An all diesen Stellen wird eine Befehlsliste erwartet, sodass ein führender Befehl
;
unerwartet ist.quelle
do
if
Die Syntax lautet:
Alle Zeilenumbrüche in der Befehlsliste oder vor dem "do" oder "done" können durch ein ";" ersetzt werden.
Eine neue Zeile (aber kein ";") ist nach dem "do" und vor dem "in" zulässig , nur um die Dinge schöner aussehen zu lassen, aber es wäre nicht sinnvoll, dort eine neue Zeile zu fordern .
quelle
if
ist ähnlich mit seinen Schlüsselwörtern: dies ist gut lesbar, wenn die Befehle kurz sind:quelle
\n
nachdemdo
es alles einem Sinne (solange man nicht darüber nachdenken , nicht in einem beliebigen setzen der Lage,\n
zwischen anderen Befehlen und args).do
,then
,else
sind nicht args - wenn sie waren, würden Sie kein Semikolon verwenden , bevor sie zugelassen werden. Sie sind Shell-Schlüsselwörter (siehetype if then elif else fi
)Kurze Antwort, da dies in der POSIX-Shell-Grammatik festgelegt ist . Alles zwischen
do
unddone
wird als Gruppe von Anweisungen betrachtet, während;
es sich um ein sequenzielles Trennzeichen handelt:Wenn zusätzlich
;
notwendig wären , würde die Norm ausdrücklich so sagen , und würdesequential_sep
nachDo
.quelle
Weil do ein Schlüsselwort ist und was danach folgt, sind im Wesentlichen Parameter. Der Bash-Interpreter weiß, dass weitere folgen. Es ist ähnlich, wie es kein ';' gibt. Folgen Sie dem i im for-Befehl. Sie können tatsächlich eine neue Zeile nach dem i in für hinzufügen und den Rest in eine neue Zeile eingeben, und es wird gut funktionieren.
quelle