Verificare se l'output di un comando contiene una determinata stringa in uno script di shell


116

Sto scrivendo uno script di shell e sto cercando di verificare se l'output di un comando contiene una determinata stringa. Penso che probabilmente dovrò usare grep, ma non sono sicuro di come. Qualcuno sa?


Il comando deve continuare a funzionare dopo aver generato la stringa di output che stai cercando o può essere chiuso immediatamente in quel momento? (Le tue due risposte differiscono in termini di semantica a questo riguardo).
Charles Duffy

Risposte:


97

Verifica il valore restituito da grep:

./somecommand | grep 'string' &> /dev/null
if [ $? == 0 ]; then
   echo "matched"
fi

che è fatto idiomaticamente in questo modo:

if ./somecommand | grep -q 'string'; then
   echo "matched"
fi

e anche:

./somecommand | grep -q 'string' && echo 'matched'

2
Questo codice non funziona con tutte le shell POSIX: lo standard POSIX richiede solo =di essere un operatore di confronto, non ==; vedi pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html
Charles Duffy

4
Inoltre, grep 'string' &>/dev/nullè sia non conforme a POSIX che molto più lento da eseguire (se stringappare all'inizio in un flusso di output lungo) rispetto a grep -q string. [L'avvertenza che c'è se vuoi essere sicuro che somecommandcontinui a funzionare anche dopo l'emissione string, nel qual caso l'uso grep -q- chiudendo il suo stdin ed uscendo dopo che la prima istanza di stringè stata vista - può essere controproducente]. (Oggetto: "non conforme a POSIX", &>è un'estensione - vedere pubs.opengroup.org/onlinepubs/009695399/utilities/… che descrive il supporto di reindirizzamento richiesto da POSIX).
Charles Duffy

Sarebbe utile se venisse spiegato perché funziona / cosa fa ogni parametro, per incoraggiare la piena comprensione della sintassi
redfox05

157

Il test $?è un anti-pattern

if ./somecommand | grep -q 'string'; then
  echo "matched"
fi

Se per caso vuoi testare solo una stringa fissa, aggiungi le opzioni F e x : grep -Fxq F sta per fisso (non interpretato) ex per l'intera linea
Erdal G.

4
Perché testare $?è anti-pattern?
Vitaly Zdanevich

1
@VitalyZdanevich presumo perché non è robusto contro la concorrenza.
Konrad Reiche

@VitalyZdanevich, per esempio, il test $?non imposta i comandi precedenti come "controllato" ai fini di set -eo la ERRtrappola, in modo che il programma possa uscire nei casi in cui si desidera per tornare semplicemente lungo il sentiero intenzionalmente-falso in seguito. Dall'altro, $?è uno stato globale volatile: è facile buttare via il suo valore per sbaglio. Ad esempio, se aggiungi una riga di registrazione simile echo "Exit status is $?", il nuovo valore in $?diventa lo stato di uscita di echo.
Charles Duffy

6

Un'altra opzione è controllare la corrispondenza delle espressioni regolari sull'output del comando.

Per esempio:

[[ "$(./somecommand)" =~ "sub string" ]] && echo "Output includes 'sub string'"

1

Uno script di shell condizionale if / else pulito:

if ./somecommand | grep -q 'some_string'; then
  echo "exists"
else
  echo "doesn't exist"
fi
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.