8

I'd like to check whether a line printed by a command contains an error message, but I'd like to also print all the output from the command (for make logs). Is there some way to get all the output of a command (unmodified) and an exit code based on the contents of that output? The closest workaround I could think about was my_command | grep -C 99999999 '^Error'.

This is similar but distinct to this question, since I care about the exit code and don't want colouring.

l0b0
  • 51,350

4 Answers4

9

Use tee and redirect it to stderr

my_command | tee /dev/stderr | grep -q '^Error'

It will save grep exit status and duplicate all the output to stderr which is visible in console. If you need it in stdout you can redirect it there later like this:

( my_command | tee /dev/stderr | grep -q '^Error' ) 2>&1

Note that grep will output nothing, but it will be on tee.

rush
  • 27,403
2

You can do this with AWK:

command 2>&1 | awk '/^Error/{exit_code=1;}/^/ END{ exit !exit_code}'

This will print all the output lines and return 0 if it finds Error and return 1 if it doesn't.

  • 1
    I had to add a print command 2>&1 | awk '/^Error/{exit_code=1;}/^/{print} END{ exit !exit_code}'

    to get this to work. Otherwise it gave mea syntax error. Note sure if this is right.

    – David Mokon Bond Jun 07 '22 at 03:16
0

You can do it with sed as well!

Here's a function to Print all + Highlight matches + Return exit code (5) if no match found:

search_regex()
{
  pattern=$1
  shift
  esc=$(printf "\033")
  sed '/'"${pattern}"'/,${s//'$esc'[32m&'$esc'[0m/g;b};$q5' "$@"
}

$ echo -e "What's up\nMr. Jones?" | search_regex "on\|up"

What's up
Mr. Jones?

Noam Manos
  • 1,031
0

Here's how you do it with sed if you don't want coloring, i.e. you want exact output:

my_command | sed '/^Error/,$b;$q1'

And since this is a bit cryptic, I try to explain how it works:

  • by default already, sed prints every line from stdin to stdout, so we've already achieved our first goal of printing every line
  • /^Error/,$ then defines a range from the line that matches the pattern /^Error/ to the end of the file ($ means the last line).
  • on this range, execute command b. b branches (i.e. jumps) to a label. If the label is omitted, it branches to end of script. sed returns with status code 0.
  • if no line matches the pattern /^Error, the range command is not executed, thus we're not jumping to the end of script. Instead, the next command is executed: $q1.
  • $q1 simply means to run command q1 on the last line ($). q1 ends the script, with status code 1