2013-08-19 19 views
12

In bash, voglio dire "se un file non contiene XYZ, quindi" fai un sacco di cose. Il modo più naturale per recepire questa in codice è qualcosa di simile:Bash condizionale al comando codice di uscita

if [ ! grep --quiet XYZ "$MyFile" ] ; then 
    ... do things ... 
fi 

Ma, naturalmente, questo non è la sintassi Bash valido. Potrei usare i backtick, ma poi testerò l'output del file. Le due alternative mi viene in mente sono:

grep --quiet XYZ "$MyFile" 
if [ $? -ne 0 ]; then 
    ... do things ... 
fi 

E

grep --quiet XYZ "$MyFile" || 
    ( ... do things ... 
    ) 

I tipi di preferire il secondo, è più Lispy e || per il controllo del flusso non è così raro nei linguaggi di scripting. Posso vedere gli argomenti anche per il primo, sebbene quando la persona legge la prima riga, non sanno perché stai eseguendo grep, sembra che lo stai eseguendo per il suo effetto principale, piuttosto che solo per controlla un ramo nella sceneggiatura.

Esiste un terzo modo più diretto che utilizza un'istruzione if e ha lo grep nelle condizioni?

+0

possibile duplicato del [incontro "operatore unario previsto" in script bash] (http://stackoverflow.com/questions/10586213/encounter-unary-operator-expected-in-bash-script) – tripleee

risposta

20

sì, c'è:

if grep --quiet ..... 
then 
    # If grep finds something 
fi 

o se il grep non riesce

if ! grep --quiet ..... 
then 
    # If grep doesn't find something 
fi 
+0

D'oh! Grazie. A mia difesa, non l'ho visto in nessun tutorial, nemmeno in quelli che parlano di controllare il codice di uscita di un comando. –

+1

'[' è una specie di alias per 'test' (che richiede anche'] '). Quindi 'se [...]' è equivalente a 'se test ...' – coldfix

+0

Cosa succede se si desidera testare più condizioni, una delle quali è lo stato di uscita di un comando? Come in: 'se [[$ OS ==" windows "&& command-exit-status == 0]]; ...' ? Posso eseguire il comando prima e salvare '$?' Ovviamente, ma mi piacerebbe il collegamento '&&' comportamento in modo che non esegua il comando a meno che '$ OS == windows'. Qualche buona idea? – GaryO

2

Questa è una questione di gusto, ovviamente, dato che ci sono molteplici soluzioni di lavoro. Quando mi occupo di un problema come questo, di solito applico wc -l dopo grep per contare le righe corrispondenti. Quindi hai un numero intero singolo che puoi valutare all'interno di una condizione di test. Se la domanda è solo se c'è una partita a tutti (il numero di linee corrispondenti non importa), applicando poi wc probabilmente è OTT e la valutazione di codice di ritorno grep s' sembra essere la soluzione migliore:

Normalmente, lo stato di uscita è 0 se vengono trovate linee selezionate e 1 in caso contrario. Ma lo stato di uscita è 2 se si è verificato un errore, a meno che non venga utilizzata l'opzione -q o --quiet o --silent e venga trovata una linea selezionata. Si noti, tuttavia, che POSIX richiede solo, per programmi come grep, cmp e diff, che lo stato di uscita in caso di errore sia maggiore di 1; è quindi opportuno, per il bene di portabilità, di utilizzare logica che mette alla prova per questa condizione generale invece di uguaglianza rigorosa con 2.

7

Non è necessario il [] (test) per controllare il ritorno valore di un comando. Basta provare:

if ! grep --quiet XYZ "$MyFile" ; then 
Problemi correlati