Chcete-li stavět na chepnerově bystrém komentáři k otázce:
-
V
[ ! condition ]
,!
je pouze argument na[
vestavěný (účinný aliastest
vestavěný); stane se, že[
/test
interpretuje argument!
jako negace. -
V
! [ condition ]
,!
je klíčové slovo shellu který neguje jakýkoli příkaz, který následuje (což je shodou okolností[
v tomto případě).
Jedna věc je ! [ condition ]
syntaxe vám implicitně dává, že negace se vztahuje na cokoli [ condition ]
vyhodnotí jako jako celek , takže pokud je to záměr, nemusíte si dělat starosti s prioritou operátorů.
Výkon , kterou zvolenou syntaxi pravděpodobně příliš nemění; rychlé testy naznačují:
-
Pokud
condition
je v obou případech doslova stejný a předává!
jako argument k[
je zanedbatelně rychlejší. -
Pokud
!
se používá jako klíčové slovo , a proto můžete podmínku zjednodušit tím, že se nebudete starat o prioritu, může být o něco rychlejší (např.! [ 0 -o 1 ]
vs.[ ! \( 0 -o 1 \) ]
; všimněte si, že specifikace POSIX. odrazuje od používání-a
a-o
kvůli nejednoznačnosti).
To znamená, pokud mluvíme o Bash , pak byste měli zvážit použití [[
místo [
, protože [[
je klíčové slovo shellu který analyzuje uzavřený výraz ve speciálním kontextu, který:
- nabízí více funkcí
- umožňuje bezpečně kombinovat výrazy s
&&
a||
- přichází s méně překvapeními
- je také o něco rychlejší (ačkoli na tom v praxi bude záležet jen zřídka)
Viz tato moje odpověď.
!
neguje ukončovací kód následujícího příkazu:
$ ! test 1 = 1 || echo $? # negate command with true expression
1
Jak je uvedeno v manuálové stránce, test
(a podobné [
builtin) exit se stavem určeným následujícím výrazem :
$ test ! 1 = 1 || echo $? # return false expression
1
$ [ ! 1 = 1 ] || echo $?
1
Pro daný výraz :
- na jedné straně negujete
test
příkaz, který ukončí se stavem true expression. - na druhé straně negujete výraz a
test
příkaz (nebo[
) ukončete s falešným stavem
Obojí bude mít stejný účinek.
Řekl bych tedy, že tyto syntaxe jsou ekvivalentní. S výhodou pro externí !
povolit negaci složených testů:
$ ! [ 1 = 1 -a 2 = 2 ] || echo $?
1