files example regex bash grep exit exit-code

files - grep regex example



Bash: One-liner para salir con el estado opuesto de un comando grep? (10)

¿Cómo puedo reducir el siguiente script de bash?

grep -P "STATUS: (?!Perfect)" recess.txt && exit 1 exit 0

Parece que debería poder hacerlo con un solo comando, pero tengo un total de 3 aquí.

Mi programa debe:

  • Leer recess.txt
  • Salir 1 (o no cero) si contiene una línea con "STATUS:" de NOT "Perfect"
  • Salga de 0 si no existe tal línea (es decir, todas las "ESTADO:" las líneas son "Perfectas")

El premio de la respuesta va a la escritura más apretada. ¡Gracias!

Archivos de ejemplo

El programa debe tener estado de salida 0 para este archivo:

FILE: styles.css STATUS: Perfect! FILE: contour-styles.css STATUS: Perfect!

El programa debe tener el estado de salida 1 (o distinto de cero) para este archivo:

FILE: styles.css STATUS: Perfect! FILE: contour-styles.css STATUS: Busted FAILURES: 1 failure Id''s should not be styled 1. #asdf


El problema con las respuestas de grep es que si el archivo está vacío, también obtendrá una respuesta limpia, como si el archivo tuviera un resultado perfecto. Así que personalmente renuncié a grep por esto y usé awk.

awk ''BEGIN{ef=2}; /STATUS: Perfect/{ ef=0;}; /STATUS: Busted/{ print;eff=3;}; END{exit (ef+eff)}'' a.txt ; echo $? This has exit status: 0 : Perfect and !Busted 2 : !Perfect and Busted 3 : Perfect and Busted 5 : !Perfect and !Busted


En realidad no es necesario utilizar exit en absoluto. Lógicamente, no importa cuál sea el resultado de grep, su script se cerrará de todos modos. Dado que el valor de salida de un script de shell es el código de salida del último comando que se ejecutó, simplemente ejecute grep como el último comando, usando la opción -v para invertir la coincidencia y corregir el valor de salida. Por lo tanto, su script puede reducirse a solo:

grep -vqP "STATUS: (?!Perfect)" recess.txt

EDITAR:

Lo sentimos, lo anterior no funciona cuando hay otros tipos de líneas en el archivo. Sin embargo, en el interés de evitar ejecutar múltiples comandos, awk puede lograr todo el shebang con algo como:

awk ''/STATUS: / && ! /Perfect/{exit 1}'' recess.txt

Si decides que quieres la salida que grep habría proporcionado, puedes hacer:

awk ''/^STATUS: / && ! /Perfect/{print;ec=1} END{exit ec}'' recess.txt


Me encontré con esto, necesitando una onlyif declaración para Puppet. Como tal, la solución de bash de Tgr no funcionaría, y no quería expandir la complejidad como en la respuesta de Christopher Neylan .

Terminé usando una versión inspirada en la respuesta de Henri Schomäcker , pero notablemente simplificada:

grep -P "STATUS: (?!Perfect)" recess.txt; test $? -eq 1

Lo que simplemente invierte el código de salida, devolviendo el éxito solo si no se encuentra el texto:

  • Si grep devuelve 0 (coincidencia encontrada), la test 0 -eq 1 devolverá 1.
  • Si grep devuelve 1 (no se encontró ninguna coincidencia), la test 1 -eq 1 devolverá 0.
  • Si grep devuelve 2 (error), la test 2 -eq 1 devolverá 1.

Que es exactamente lo que quería: devolver 0 si no se encuentra una coincidencia, y 1 de lo contrario.


Para que funcione con set -e en un sub-shell con ( y ) :

$ cat test.sh #!/bin/bash set -ex (! ls /tmp/dne) echo Success $ ./test.sh + ls /tmp/dne ls: cannot access /tmp/dne: No such file or directory + echo Success Success $ mkdir /tmp/dne $ ./test.sh + ls /tmp/dne $


Si alguien llega aquí buscando una manipulación de código de retorno de bash:

(grep <search> <files> || exit 0 && exit 123;)

esto devolverá 0 (éxito) cuando grep no encuentre nada, y devolverá 123 (error) cuando lo haga. Los paréntesis están en caso de que alguien lo pruebe como está en el indicador de shell. con paréntesis no se desconectará en la salida, sino que simplemente saldrá de la subshell con el mismo código de error.

Lo uso para una rápida comprobación de sintaxis en archivos js:

find src/js/ -name /*js -exec node /{/} /; 2>&1 | grep -B 5 SyntaxError || exit 0 && exit 1;


Solo negate el valor de retorno.

! grep -P "STATUS: (?!Perfect)" recess.txt


Solo negar el valor de retorno no funciona en un contexto set -e. Pero puedes hacer:

! grep -P "STATUS: (?!Perfect)" recess.txt || false


También necesitaba tal solución para escribir títeres solo en declaraciones y se me ocurrió el siguiente comando:

/bin/grep --quiet ''root: [email protected]'' /etc/aliases; if [ $? -eq 0 ]; then test 1 -eq 2; else test 1 -eq 1; fi;


Usa el especial ? variable

grep -P "STATUS: (?!Perfect)" recess.txt exit $((1-$?))

(Pero tenga en cuenta que grep también puede devolver 2, por lo que no está claro qué desea que ocurra en tales casos).


[ $(grep -c -P "STATUS: (?!Perfect)" recess.txt) -eq 0 ]