variables – Bash: Verifying numbers inside line closer to “big” log file – Education Career Blog

What I’m trying to do: Make a bash script that performs some tests on my system, wich than reads some log files, and in the end points me some analyzes.

I have, for example, a log file (and although it’s not so big sometimes, I want to save proccess when possible) that has in the end something like this:

Ran 6 tests with 1 failures and 0 errors in 1.042 seconds.
Tearing down left over layers:
Tear down Products.PloneTestCase.layer.PloneSite in 0.463 seconds.
Tear down Products.PloneTestCase.layer.ZCML in 0.008 seconds.

And I already have this bash line, that takes the line I want (the one with failures and errors):

error_line=$(tac $p.log | grep -m 1 '1-9 .* \(failures\|errors\)')

Obs: Could anyone answer me if ‘tac’ passes the proccess to grep for each line of the file, or first it load the hole file on memory and than grep runs on the hole “memory variable”? Cause I was thinking in run the grep to each line, and when the line I want comes, I’d stop the “cating” proccess.
If it does work this way (“grepping” each line), when grep finds what it want (with the -m 1 option), it stops the tac proccess? How I’d do that?

Also, do you know a better way?

Continuing…

So, the result of the command is:

Ran 6 tests with 1 failures and 0 errors in 1.042 seconds.

Now, I want to check that both the ‘1’ AND the ‘0’ values on the $error_line variable are equal to 0 (like they’re not on this case), so that if any of them is different I can perform some other proccess to sinalyze that some error or failure was found.

Answers?

,

When grep exits because the pattern is found, a SIGPIPE is sent to tac causing it to exit so it won’t continue to run needlessly.

read failures errors <<< $(tac $p.log | grep -Pom 1 '(?<= )0-9*(?= *(failures|errors))')
if  $failures == 0 && $errors == 0 
then
    echo "success"
else
    echo "failure"
fi

The grep command will output only the numbers found preceding the words “failures” and “errors” without outputting any of the other text on the line.

Edit:

If your grep doesn’t have -P, change the first line above to:

read failures errors <<< $(tac $p.log | grep -om 1 ' 0-9* *\(failures\|errors\)' | cut -d ' ' -f 2

or, to use a variation of Ignacio’s answer, to:

read failures errors <<< $(tac $p.log | awk '/^Ran/ {printf "%s\n%s\n", $5, $8}'

,

awk:

/^Ran / {
  print "No failures: " ($5 == 0)
  print "No errors: " ($8 == 0)
}

,

for very big log files, its better to use grep first to find the patterns you need, then awk to do other processing.

   grep "^Ran" very_big_log_file | awk '{print $5$8=="00"?"no failure":"failure"}'

Otherwise, just awk will do.

awk '{print $5$8=="00"?"no failure":"failure"}'

Leave a Comment