How can I reduce the following bash script?
grep -P \"STATUS: (?!Perfect)\" recess.txt && exit 1
exit 0
It seems like I should be able
Since someone already posted a Puppet solution, I might as well add how to invert a shell command run by Ansible:
- name: Check logs for errors
command: grep ERROR /var/log/cassandra/system.log
register: log_errors
failed_when: "log_errors.rc == 0"
I.e. you just set the failed condition to the return code being 0. So this command fails if we do find the word ERROR in our logs.
I chose this rather than grep -v
as that also inverts grep's output, so we would receive all DEBUG/INFO/WARN lines in log_errors.stdout_lines
which we do not want.
[ $(grep -c -P "STATUS: (?!Perfect)" recess.txt) -eq 0 ]
You actually don't need to use exit
at all. Logically, no matter what the result of grep, your script is going to exit anyway. Since the exit value of a shell script is the exit code of the last command that was run, just have grep
run as the last command, using the -v
option to invert the match to correct the exit value. Thus, your script can reduce to just:
grep -vqP "STATUS: (?!Perfect)" recess.txt
EDIT:
Sorry, the above does not work when there are other types of lines in the file. In the interest of avoiding running multiple commands though, awk
can accomplish the entire shebang with something like:
awk '/STATUS: / && ! /Perfect/{exit 1}' recess.txt
If you decide you want the output that grep would have provided, you can do:
awk '/^STATUS: / && ! /Perfect/{print;ec=1} END{exit ec}' recess.txt
The problem with the grep answers is that if the file is empty you also get a clean response, as if the file had a perfect. So personally I gave up on grep for this and used 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
Just negate the return value.
! grep -P "STATUS: (?!Perfect)" recess.txt