2016-03-26 15 views
9

Sono stato scripting Bash per un po 'e mi chiedo se c'è qualche differenza tra queste due forme di negazione con il comando test:C'è una differenza tra la negazione prima/dopo un comando di test?

if [ ! condition ]; then 
fi 

if ! [ condition ]; then 
fi 

La prima dice alla shell di passare gli argomenti per testare ! condition , lasciando che il programma si occupi della negazione stessa. D'altra parte, il secondo passa condition per testare e lascia che la shell stessa annulli il codice di errore.

Ci sono delle insidie ​​di cui dovrei essere a conoscenza quando scelgo tra queste due forme? Quali valori di $condition potrebbero rendere i risultati diversi tra loro?

(mi sembra di ricordare la lettura di un articolo qualche tempo fa discutere di questo, ma non mi ricordo come trovarlo/esattamente ciò che è stato discusso.)

+1

Non proprio una trappola, dal momento che è difficile costruire uno scenario realistico in cui ciò accada, ma tieni presente che in '! [condizione] 'il'! 'è un operatore di shell, che nega lo stato di uscita di un comando, mentre in' [! condizione] 'il'! 'è solo un argomento stringa per il comando' ['. Dopo 'foo ="! Bar "', confronta '[" $ pippo "]' con '[$ pippo]'. – chepner

risposta

6

di costruire su chepner 's commento perspicace sulla questione:

  • Nel [ ! condition ], il ! è solo un argomento a [ incorporato (un alias effettivo del test incorporato); succede così che [/test interpreta l'argomento ! come negazione.

  • In ! [ condition ], il ! è una parola shell che nega qualunque comando è seguito da (che risulta essere [ in questo caso).

Una cosa che la sintassi ! [ condition ] implicitamente si dà è che la negazione si applica a tutto ciò che viene valutato come [ condition ]nel suo complesso, quindi se questo è l'intento, non è necessario preoccuparsi di precedenza degli operatori.

dal punto di vista delle prestazioni, la cui sintassi scelta probabilmente non fa molta differenza; test rapidi suggeriscono:

  • Se condition è letteralmente lo stesso in entrambi i casi, passando il ! come argomento per [ è trascurabile più veloce.

  • Se ! viene utilizzato come parola chiave , e si sono quindi in grado di semplificare la condizione da non preoccuparsi di precedenza, può essere leggermente più veloce (ad esempio, ! [ 0 -o 1 ] vs. [ ! \(0 -o 1 \) ], notare che le specifiche POSIX scoraggia. uso di -a e -o a causa di ambiguità).

Detto questo, se stiamo parlando di Bash, allora si dovrebbe considerare l'utilizzo [[ invece di [, perché [[ è una parola chiave shell che analizza l'espressione racchiusa in uno speciale contesto che:

  • offre più funzionalità
  • al bassi di combinare in modo sicuro le espressioni con && e ||
  • viene fornito con un minor numero di sorprese
  • è anche leggermente più veloce (anche se raramente materia in pratice)

Vedi this answer di mine.

2

! nega il codice di uscita del seguente comando:

$ ! test 1 = 1 || echo $? # negate command with true expression 
1 

Come detto in pagina man test (e [ built-simile) uscita con lo stato determinato dalla seguente espressione:

$ test ! 1 = 1 || echo $? # return false expression 
1 
$ [ ! 1 = 1 ] || echo $? 
1 

Per una data espressione:

  • da un lato si nega il comando test che escono con il vero stato di espressione.
  • dall'altra parte, si nega l'espressione e il comando test (o [) uscita con il suo status falso

Entrambi avranno lo stesso effetto.

Quindi direi che queste sintassi sono equivalenti. Con il vantaggio per esterni ! per consentire test composti negate:

$ ! [ 1 = 1 -a 2 = 2 ] || echo $? 
1 
+0

Si potrebbe notare che un piccolo adattamento del terzo esempio nel primo set riporta anche '1':' test! falso || echo $? '. Questo perché il test sta verificando se la stringa ('true' o' false') è vuota o meno. Allo stesso modo con il secondo esempio nel primo set; la sostituzione di 'true' di' false' non cambia il risultato. –

+0

Hai ragione. Sostituito con quello che dovrei essere: un'espressione. – SLePort

+0

Forse dovresti notare che '==' funziona su 'bash' ma non su' dash'. –

Problemi correlati