我想检查命令打印的行是否包含错误消息,但我还想打印命令的所有输出(用于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/
然后定义从与模式匹配的行到文件末尾($
表示最后一行)的范围。- 在此范围内,执行命令
b
。b
分支(即跳转)到标签。如果省略标签,则会分支到脚本末尾。sed
返回状态码为 0。 - 如果没有行与模式匹配
/^Error
,则不会执行范围命令,因此我们不会跳到脚本末尾。相反,执行下一个命令:$q1
。 $q1
只是意味着q1
在最后一行($
)运行命令。q1
结束脚本,并带有状态码1