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?


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'

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

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'"

1

Um script de shell condicional if / else limpo:

if ./somecommand | grep -q 'some_string'; then
  echo "exists"
else
  echo "doesn't exist"
fi
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.