如何获取 grep 退出代码但打印所有行?

如何获取 grep 退出代码但打印所有行?

我想检查命令打印的行是否包含错误消息,但我还想打印命令的所有输出(用于make日志)。有什么办法可以得到全部命令的输出(未修改)和基于该输出内容的退出代码?我能想到的最接近的解决方法是my_command | grep -C 99999999 '^Error'

这与以下类似但不同这个问题,因为我关心退出代码并且不想着色。

答案1

使用tee并将其重定向到 stderr

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

它将保存grep退出状态并将所有输出复制到控制台中可见的 stderr。如果您在标准输出中需要它,您可以稍后将其重定向到那里,如下所示:

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

请注意,grep不会输出任何内容,但它会打开tee

答案2

您可以使用 AWK 执行此操作:

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

这将打印所有输出行,如果找到则返回 0 Error,如果没有则返回 1。

答案3

你可以这样做sed还有!

这是一个打印全部 + 的函数强调匹配+返回退出代码(5) 如果没有找到匹配项:

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

$ echo -e "怎么了\n琼斯先生?" | search_regex“上\|上”

什么是向上
J先生是吗?

答案4

这是你如何做到的sed如果你不想着色,即你想要精确的输出:

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

由于这有点神秘,我尝试解释它是如何工作的:

  • 默认情况下,sed打印从 stdin 到 stdout 的每一行,因此我们已经实现了打印每一行的第一个目标
  • /^Error/,$/^Error/然后定义从与模式匹配的行到文件末尾($表示最后一行)的范围。
  • 在此范围内,执行命令bb分支(即跳转)到标签。如果省略标签,则会分支到脚本末尾。sed返回状态码为 0。
  • 如果没有行与模式匹配/^Error,则不会执行范围命令,因此我们不会跳到脚本末尾。相反,执行下一个命令:$q1
  • $q1只是意味着q1在最后一行($)运行命令。q1结束脚本,并带有状态码1

相关内容