Sind "wenn" und "dann" eigentlich Programme

15

Ich habe gelesen, dass Semikolon zum Trennen von Programmen verwendet wird:

$ echo 3; ls -la

Bedeutet das if, thenund handelt elsees sich hier um separate Programme?

$ if [ $VARIABLE == abcdef ] ; then echo yes ; else echo no ; fi

Bei dieser Frage handelt es sich nicht um Semikolons.

Maxim Koretskyi
quelle
2
Mögliches Duplikat von Semikolon in bedingten Strukturen
Stephen Rauch
1
@StephenRauch Nicht wirklich ein Duplikat. Es ist eher ein vernünftiges Ergebnis dieses Q, als ein Versuch, weiter zu verstehen.
Gypsy Spellweaver
Mehr Programm-y Formulierung:[ $variable == abcdef ] && echo yes || echo no
Hagen von Eitzen
2
@HagenvonEitzen das ist nicht unbedingt gleichbedeutend, wenn die Anweisung innerhalb des ersten Zweigs fehlschlägt, wird auch die zweite ausgeführt.
Morgen
Mögliches Duplikat von Was sind die Steuerungs- und Umleitungsoperatoren der Shell?
G-Man sagt, dass Monica am

Antworten:

26

Die ;getrennten Aussagen (lose gesprochen). Es ist (fast) immer möglich, eine ;durch eine neue Zeile zu ersetzen .

Zu sagen, dass ;zwei Programme voneinander getrennt sind ifund then"Programme" sein müssen, ist etwas zu einfach, da eine Aussage über reservierte Wörter, Shell - Funktionen, eingebaute Dienstprogramme und externe Dienstprogramme sowie Kombinationen davon unter Verwendung von Pipes und booleschen Operatoren usw. Getroffen werden kann . etc.

Beide ifund thensind reservierte Wörter in der Shell-Grammatik , keine "Programme". Hier werden sie verwendet, um das aufzubauen, was technisch ein zusammengesetzter Befehl genannt wird .

echoist wahrscheinlich ein in die Shell eingebautes Dienstprogramm (muss es aber nicht sein) und lsist wahrscheinlich ein externes Dienstprogramm (oder "Programm", wie Sie sagen).

Kusalananda
quelle
7

Während dies eine faire erste Annäherung ist, wenn man anfängt, die Grundlagen der Verwendung von Shells zu erlernen, wird auf der Ebene von "hier wird ein Programm ausgeführt" und "hier werden mehrere Programme nacheinander in einer einzigen Zeile ausgeführt" ist es eigentlich nicht wahr.

Für Anfänger ist es schwieriger zu verstehen, aber die richtige Erklärung ist, dass die Shell-Sprache eine Computersprache ist . Es hat eine Syntax . Diese Syntax umfasst verschiedene lexikalische Elemente, darunter (unter anderem) Zeilenumbrüche, Operatoren, Wörter und reservierte Wörter.

if, then, else, Und fisind alle reservierten Wörter . Sie haben besondere Bedeutungen beim Parsen der Eingabe, die man einer Shell gemäß ihrer Grammatik gibt . In ähnlicher Weise ;ist ein Separator Operator .

Die Eingabe in der Shell-Sprache wird somit als Ganzes als Computerprogramm verstanden, das von einem anderen Programm, einem Interpreter , der Shell interpretiert wird. Die einzelnen grammatikalischen Teile sind keine Programme. Mit der Shell-Sprache können Sie (andere) Programme angeben, die von der Shell ausgeführt werden sollen.

[ist kein spezielles lexikalisches Element in der Shell-Grammatik wie ein Operator. Es ist ein gewöhnliches Wort , das ein solches Programm benennt [. Viele Shells haben eine integrierte Version dieses Programms, die im Code des Shell-Programms selbst kombiniert ist. Sie können jedoch auch ein externes Programm mit diesem Namen finden, z. B. /bin/[oder /usr/bin/[, das von anderen Programmen als Shells aufgerufen werden kann. Ebenso ]ist es auch kein spezielles Shell-Lexikonelement. Es ist ein gewöhnliches Wort, das zum Argument für das [Programm wird. Das [Programm verlangt, dass sein letztes Argument, wenn es ausgeführt wird, sein muss ], das es dann ignoriert.

Ein anderes ähnliches Programm, das in Ihrer Frage genannt wird, ist echo. Wieder haben die meisten Shells eine eingebaute Version dieses Programms. Es gibt aber auch eine externe Version des Programms, die irgendwo wie /bin/echooder /usr/bin/echofür andere Programme als Shells aufgerufen werden kann.

Ein drittes in Ihrer Frage genanntes Programm ist ls. Shells haben im Allgemeinen keine integrierten Versionen dieses Programms, und es ist ein externes Programm, das sich irgendwo wie /bin/lsoder befindet /usr/bin/ls.

Weitere Informationen zur Bourne Again-Shell finden Sie in den grundlegenden Shell-Funktionen der GNU Bourne Again-Shell-Info-Dokumentation. Andere Muscheln haben natürlich andere Grammatiken. Die Single Unix Specification beschreibt eine Syntax, an die sich alle POSIX-konformen Shells (in ihren POSIX-konformen Modi) halten sollen.

Weitere Lektüre

  • " Shell Grammatik ". Shell-Befehlssprache . Basisspezifikationen Problem 7. Die offene Gruppe. IEEE 1003.1-2008. ISBN 1937218812.
  • test. Dienstprogramme . Basisspezifikationen Problem 7. Die offene Gruppe. IEEE 1003.1-2008. ISBN 1937218812.
  • " Shell Grammatik ". Das Z-Shell-Handbuch . Version 5.3.1. 2017.
JdeBP
quelle
5

Es ist eigentlich nicht weit hergeholt if, thenund elseals externe Programme zu denken . Tatsächlich wurde die Thompson-Shell in der ursprünglichen 1. Edition von Unix implementiert ifund gotoals externe Programme. Dies ist möglich, weil der Unterprozess Dateideskriptoren mit dem Shell-Prozess gemeinsam nutzt, sodass ein (Weiter-) Goto nur die Eingabe lesen musste, bis er die Zielbezeichnung findet und dann beendet wird. Siehe Thompson-Shell .

Johan Myréen
quelle
Oder sehen Sie in der Tat Laurent Bercots ifund ifelse, die Teile von sind execline. Dies kommt jedoch nicht ifin Frage.
JdeBP
2
"Es ist eigentlich nicht weit hergeholt, wenn, dann und sonst als externe Programme zu denken" Nun, es ist, weil sie es nicht sind.
Leichtigkeit Rennen mit Monica
2

Das thenundelse sind keine Programme. Die anderen Teile sind. Beachten Sie, dass es kein ;'direkt nach ihnen gibt, aber nach dem Befehl, dem sie vorangehen.

Das [ ... ] ist ein Befehl und benötigt das ;if gefolgt vom Beginn eines anderen Befehls.

AFAIK, alle Kontrollstrukturen in Bash und wahrscheinlich die meisten * nix-Shells, sind gleich. Sie sind Anweisungen an den Dolmetscher. Der Test oder die Bedingung verwendet andererseits ein Programm / einen Prozess, der "ausgeführt" wird und Befehle sind. Da thenes sich um einen Teil der Zeile handelt, die zum echoBefehl führt, muss dieser durch eine neue Zeile vom vorherigen Befehl getrennt werden [ ... ]. Es muss nicht von dem Befehl getrennt werden, den es steuert echo yes.

Rechtlich, obwohl hässlich und schwer zu lesen, könnten Sie dies auch tun.

if [ $VARIABLE == abcdef ]
then echo yes
else echo no
fi

Beachten Sie, dass ;zwischen den Steuerelementen hier überhaupt keine Notwendigkeit besteht , obwohl sie sich nicht in einer eigenen Leitung befinden.

Interessanterweise ist die gesamte Kontrollstruktur ( if ... fi) ein Shell-Befehl, und das Ganze muss mit einem Zeilenumbruch oder einem Zeilenumbruch enden ;. Die letzte Zeile kann nicht sein fi echo done, muss aber seinfi; echo done . Das Gleiche wie eine Zuweisung VARIABLE='abcdef'ist ein Befehl.

Obwohl die gesamten Kontrollstrukturen Befehle sind, sind sie immer noch keine Programme.

Zigeuner-Zauberwirker
quelle
1

if, elif , then, Und fiverwendet , werden alle reservierten Schlüsselwörter einer der Konstrukte als Verbindung Befehl in der Schale bezeichnet umzusetzen, was bedeutet , es nicht ein Befehl sein kann (oder besser gesagt, ein anderer Befehl) in der Schale von jedem dieser Namen. Der Zweck der ;im Allgemeinen nicht Befehle zu trennen, aber einen Befehl zu beenden Liste . Das Folgende ist zum Beispiel eine gültige ifAussage:

if echo foo; echo bar; echo baz; then echo done; echo really done; fi

Die Bedingung der ifAnweisung ist die Befehlsliste echo foo; echo bar; echo baz. Der Parser weiß, dass die Bedingung beendet ist, da thendas unmittelbar auf ein Semikolon folgende Kommando kein Befehl sein kann, da es sich um ein reserviertes Schlüsselwort handelt. Somit weiß es, was folgt then der Beginn des Körpers ist. Ebenso fiist es ein reserviertes Schlüsselwort und kann daher kein dritter Befehl im Hauptteil der ifAnweisung sein, sondern markiert das Ende des zusammengesetzten Befehls.

chepner
quelle
danke, wenn dies verwendet wird if program1 foo; program2 bar; program3 baz; , welcher Programmstatus sollte sein 0, damit die Shell fortfährt then? Der Letzte?
Maxim Koretskyi
Nur program3 baz. Der Beendigungsstatus einer Befehlsliste ist der Beendigungsstatus des letzten Befehls in dieser Liste. Die anderen beiden können fehlschlagen, ohne die Bedingung zu beeinflussen.
Chepner