Verificar se a saída de um comando contém uma certa string em um script de shell

116

Estou escrevendo um script de shell e tentando verificar se a saída de um comando contém uma determinada string. Estou pensando que provavelmente terei que usar grep, mas não tenho certeza de como. Alguém sabe?

user1118764
fonte
O comando precisa continuar em execução após gerar a string de saída que você está procurando ou pode ser fechado imediatamente nesse momento? (Suas duas respostas diferem em termos de sua semântica a esse respeito).
Charles Duffy

Respostas:

97

Teste o valor de retorno de grep:

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

que é feito de forma idiomática assim:

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

e também:

./somecommand | grep -q 'string' && echo 'matched'
perreal
fonte
2
Este código não funciona com todos os shells POSIX: O padrão POSIX requer apenas =ser um operador de comparação, não ==; consulte pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html
Charles Duffy
4
Além disso, grep 'string' &>/dev/nullnão é compatível com POSIX e é muito mais lento para executar (se stringaparecer no início de um fluxo de saída longo) do que grep -q string. [A advertência que existe se você quiser ter certeza de que somecommandcontinuará funcionando mesmo após a emissão string, caso em que usar grep -q- fechando seu stdin e saindo após a primeira instância de stringser vista - pode ser contraproducente]. (Re: "não compatível com POSIX", &>é uma extensão - consulte pubs.opengroup.org/onlinepubs/009695399/utilities/… que descreve o suporte de redirecionamento mandatado por POSIX).
Charles Duffy
Ajudaria se fosse explicado por que isso funciona / o que cada parâmetro faz, para encorajar o entendimento completo da sintaxe
redfox05
157

O teste $?é um anti-padrão

if ./somecommand | grep -q 'string'; then
  echo "matched"
fi
esteira
fonte
Se por acaso você quiser apenas testar uma string fixa, adicione as opções F e x : grep -Fxq F significa fixo (não interpretado) ex para toda a linha
Erdal G.
4
Por que o teste $?é anti-padrão?
Vitaly Zdanevich,
1
@VitalyZdanevich Presumo que seja porque não é robusto contra simultaneidade.
Konrad Reiche,
@VitalyZdanevich, por exemplo, o teste $?não define os comandos anteriores como "verificados" para fins de set -eou para a ERRarmadilha, então seu programa pode sair nos casos em que você deseja que ele simplesmente retorne para o caminho intencionalmente falso mais tarde. Por outro lado, $?é um estado global volátil - é fácil jogar fora seu valor por acidente. Por exemplo, se você adicionar uma linha de registro como echo "Exit status is $?", o novo valor em $?se tornará o status de saída de echo.
Charles Duffy
6

Outra opção é verificar a correspondência da expressão regular na saída do comando.

Por exemplo:

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

Um script de shell condicional if / else limpo:

if ./somecommand | grep -q 'some_string'; then
  echo "exists"
else
  echo "doesn't exist"
fi
Ehsan Barkhordar
fonte