Was bewirkt die Eingabe eines einzelnen Ausrufezeichens in Bash?

20

Bash verwendet Ausrufezeichen für Verlaufserweiterungen, wie in den Antworten auf diese Frage erläutert (führt z. B. sudo !!die vorherige Befehlszeile mit aus sudo). Ich kann jedoch nirgendwo etwas finden, das erklärt, was das Ausführen des folgenden Befehls (dh eines einzelnen Ausrufezeichens) bewirkt:

!

Es scheint nichts zu drucken und mit 1 zu beenden, aber ich bin nicht sicher, warum es das tut. Ich habe online und in der Bash-Manpage nachgesehen, kann aber nichts finden, abgesehen von der Tatsache, dass es sich um ein "reserviertes Wort" }handelt.

}

druckt einen Fehler:

bash: syntax error near unexpected token `}'
Josh
quelle
1
Nichts. !Gibt den "Start" eines Verlaufserweiterungsausdrucks an.
Jordan

Antworten:

47

Der Einsame !am Anfang eines Befehls negiert den Beendigungsstatus des Befehls oder der Pipeline : Wenn der Befehl beendet 0wird, springt er auf 1(Fehler) und wenn er nicht auf Null beendet wird, wird er in einen 0(erfolgreichen) Beendigungsstatus umgewandelt.

Diese Verwendung ist im Bash-Handbuch dokumentiert:

Wenn das reservierte Wort '!' Vor der Pipeline ist der Exit-Status die logische Negation des Exit-Status wie oben beschrieben.

A !ohne folgenden Befehl negiert den leeren Befehl, der nichts tut und true zurückgibt (entspricht dem :Befehl ). Es invertiert also das Wahr in ein Falsch und wird mit dem Status 1 beendet, erzeugt jedoch keinen Fehler.


Es gibt auch andere Verwendungen !innerhalb der Befehle testund [[, bei denen sie einen bedingten Test negieren. Diese haben nichts mit dem zu tun, was Sie sehen. Sowohl in Ihrer Frage als auch in diesen Fällen hat dies nichts mit der Erweiterung der Historie zu tun und !wird von anderen Begriffen getrennt.

Michael Homer
quelle
5
+1 für die erste Antwort, um zu erklären, was tatsächlich ausgeführt wird und warum dies den Rückkehrcode erklärt.
Jeff Schaller
11

Das einzige Ausrufezeichen finden Sie im Bash-Handbuch, Abschnitt 3.2.2 Pipelines

Wenn das reservierte Wort '!' Vor der Pipeline ist der Exit-Status die logische Negation des Exit-Status wie oben beschrieben.

$ ! true; echo $?
1
$ ! false; echo $?
0

Auch Abschnitt 3.2.4.2 Bedingte Konstrukte

! Ausdruck

Wahr, wenn der Ausdruck falsch ist.


Siehe auch Abschnitt 4.1 Bourne Shell Builtins

! ausdr

True, wenn expr false ist.


Es sollte auch beachtet werden, dass !die Ersetzung des Verlaufs gestartet wird, sofern nicht gefolgt von: einem Leerzeichen, einem Tabulator, dem Ende der Zeile, '=' oder '(' (wenn die Option extglob shell mit der integrierten Option shopt aktiviert ist).

Jesse_b
quelle
0

Denn !wird in Vergleichen verwendet und bedeutet NICHT .

Beispielsweise:

a=3
b=2

[ $a -eq $b ] && echo "Equal"
[ ! $a -eq $b ] && echo "Not equal"
# of cause last comparison is possible to write as:
[ $a -eq $b ] || echo "Not equal"

[ $a -eq $b ]
echo $?
1
[ ! $a -eq $b ]
echo $?
0
Yurij Goncharuk
quelle
1
Das ist die Bedeutung von !als Argument für den testBefehl (einschließlich der in bash integrierten Version), nicht die Bedeutung von !bei Verwendung in der Befehlsposition.
Gilles 'SO- hör auf böse zu sein'
1
Es müsste sein ! [...], die Frage in diesem Fall zusammenzubringen.
Michael Homer
Einverstanden mit @Gilles und @Michael Homer. Ich wusste das []ist test. Ich bin ein bisschen beeilt.
Yurij Goncharuk
-2

! Eingebauter Befehl kehrt den Sinn einer Pipeline um.

Andere Verwendungen:

#! Mit dem integrierten Befehl wird der angegebene Interpreter aufgerufen, um das Skript auszuführen.

! Ereignisbezeichner, markiert ein Befehlszeilenwort als Verlaufsersetzung

!= Ungleichungsoperator

$! Shell-Variable, gibt die Prozessnummer des letzten Hintergrundbefehls zurück.

Bharat
quelle
Zum Hinzufügen kann man! $ Verwenden, um das letzte Wort des vorherigen Befehls wie ls -l /tmp cd !$ folgt zu verwenden : Dadurch gelangen Sie in das Verzeichnis / tmp.
Hopping Bunny
-3

! gefolgt von einer Zeichenfolge führt den zuletzt ausgeführten Befehl aus (der sich noch im Befehlspuffer befindet), der mit der angegebenen Zeichenfolge begonnen hat. Vielleicht hat die Shell gerade herausgefunden, dass kein vorheriger Befehl mit <null> begann.

pdelmonte
quelle
3
Ihnen ist aufgefallen, dass die Frage keine bestimmte Zeichenfolge enthält ...?
Jeff Schaller