Um auf Chepners aufschlussreichem Kommentar zu dieser Frage aufzubauen:
-
In
[ ! condition ]
, die!
ist nur ein Argument bis[
eingebaut (ein effektiver Alias destest
eingebaut); es passiert also, dass[
/test
interpretiert Argument!
als Verneinung. -
In
! [ condition ]
, die!
ist ein Shell-Schlüsselwort das negiert jeden Befehl, der ihm folgt (was zufällig[
ist in diesem Fall).
Eine Sache, die ! [ condition ]
Syntax gibt Ihnen implizit, dass die Negation für alles [ condition ]
gilt wertet als Ganzes aus , also wenn das die Absicht ist, brauchen Sie sich keine Gedanken über die Operatorpriorität zu machen.
Leistungsmäßig , welche Syntax Sie wählen, macht wahrscheinlich keinen großen Unterschied; Schnelltests empfehlen:
-
Wenn
condition
ist in beiden Fällen buchstäblich gleich, wobei der!
übergeben wird als Argument für[
ist unwesentlich schneller. -
Wenn
!
wird als Schlüsselwort verwendet , und Sie können daher die Bedingung vereinfachen, indem Sie sich keine Gedanken über den Vorrang machen, kann es etwas schneller sein (z. B.! [ 0 -o 1 ]
vs.[ ! \( 0 -o 1 \) ]
; Beachten Sie, dass die POSIX-Spezifikation. rät von der Verwendung von-a
ab und-o
wegen Unklarheit).
Das heißt, wenn wir über Bash sprechen , dann sollten Sie erwägen, [[
zu verwenden statt [
, weil [[
ist ein Shell-Schlüsselwort das den eingeschlossenen Ausdruck in einem speziellen Kontext analysiert, der:
- bietet mehr Funktionen
- ermöglicht es Ihnen, Ausdrücke sicher mit
&&
zu kombinieren und||
- kommt mit weniger Überraschungen
- ist auch etwas schneller (obwohl das in der Praxis selten eine Rolle spielt)
Siehe diese Antwort von mir.
!
negiert den Exit-Code des folgenden Befehls:
$ ! test 1 = 1 || echo $? # negate command with true expression
1
Wie in der Manpage gesagt, test
(und ähnlich [
builtin) beenden Sie mit dem Status, der durch den folgenden Ausdruck bestimmt wird:
$ test ! 1 = 1 || echo $? # return false expression
1
$ [ ! 1 = 1 ] || echo $?
1
Für einen gegebenen Ausdruck :
- auf der einen Seite negierst du den
test
Befehl, der mit dem wahren Ausdrucksstatus beendet wird. - auf der anderen Seite negierst du einen Ausdruck und den
test
Befehl (oder[
) mit falschem Status beenden
Beide haben den gleichen Effekt.
Ich würde also sagen, dass diese Syntax äquivalent ist. Mit dem Vorteil für externe !
um zusammengesetzte Tests zu negieren :
$ ! [ 1 = 1 -a 2 = 2 ] || echo $?
1