Comprobación de si la salida de un comando contiene una determinada cadena en un script de shell


116

Estoy escribiendo un script de shell y estoy tratando de verificar si la salida de un comando contiene una determinada cadena. Estoy pensando que probablemente tenga que usar grep, pero no estoy seguro de cómo. ¿Alguien sabe?


¿El comando debe seguir ejecutándose después de generar la cadena de salida que está buscando o puede cerrarse inmediatamente en ese momento? (Sus dos respuestas difieren en términos de su semántica a este respecto).
Charles Duffy

Respuestas:


97

Pruebe el valor de retorno de grep:

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

que se hace idiomáticamente así:

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

y también:

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

2
Este código no funciona con todos los shells POSIX: el estándar POSIX solo requiere =ser un operador de comparación, no ==; ver pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html
Charles Duffy

4
Además, no grep 'string' &>/dev/nulles compatible con POSIX y es mucho más lento de ejecutar (si stringaparece temprano en un flujo de salida largo) que grep -q string. [La advertencia que hay que hacer es asegurarse de que se somecommandsiga ejecutando incluso después de emitir string, en cuyo caso usar grep -q, cerrando su stdin y saliendo después de que stringse vea la primera instancia de , puede ser contraproducente]. (Re: "no compatible con POSIX", &>es una extensión; consulte pubs.opengroup.org/onlinepubs/009695399/utilities/… que describe el soporte de redireccionamiento obligatorio de POSIX).
Charles Duffy

Ayudaría si se explicara por qué funciona / qué hace cada parámetro, para fomentar la comprensión completa de la sintaxis
redfox05

157

La prueba $?es un anti-patrón

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

Si por casualidad solo desea probar una cadena fija, agregue las opciones F y x : grep -Fxq F significa fijo (no interpretado) yx para toda la línea
Erdal G.

4
¿Por qué probar $?es anti-patrón?
Vitaly Zdanevich

1
@VitalyZdanevich Supongo que porque no es robusto contra la concurrencia.
Konrad Reiche

@VitalyZdanevich, por ejemplo, las pruebas $?no configuran los comandos anteriores como "comprobados" a los efectos de set -ela ERRtrampa, por lo que su programa puede salir en los casos en que desee que simplemente regrese por la ruta intencionalmente falsa más adelante. Por otro lado, $?es un estado global volátil: es fácil tirar su valor por accidente. Por ejemplo, si agrega una línea de registro como echo "Exit status is $?", el nuevo valor en se $?convierte en el estado de salida de echo.
Charles Duffy

6

Otra opción es verificar la coincidencia de expresiones regulares en la salida del comando.

Por ejemplo:

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

1

Un script de shell condicional if / else limpio:

if ./somecommand | grep -q 'some_string'; then
  echo "exists"
else
  echo "doesn't exist"
fi
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.