grep - 退出 1 - 如果匹配

grep - 退出 1 - 如果匹配

我有一个像这样的 bash 函数:

run_mongo(){
  mongo foo bar baz 2>&1  # send stderr to stdout
}

不幸的是,如果出现错误,这个 mongo 命令不会以 1 退出,所以我必须在 stdout/stderr 上进行匹配

如果有第一个匹配,是否有某种方法可以使用 grep 以 code > 0 退出?像这样的东西:

run_mongo | grep -e "if stdout/stderr matches this we exit with 1"

我认为执行此操作的方法如下:

run_mongo | grep -e "if stdout/stderr matches" | killer

其中 Killer 是一个一旦获得第一个标准输入就终止的程序。

答案1

是的,你可以用grep -vz它来告诉grep你找到与你给它的模式不匹配的行(-v)并立即读取整个输入(z),这样一个匹配就意味着整个事情失败:

$ printf 'foo\nbar\n' | grep -zqv foo && echo no || echo yes
yes
$ printf 'foo\nbar\n' | grep -zq foo && echo no || echo yes
no

所以,就你的情况而言,类似:

run_mongo(){
  mongo foo bar baz 2>&1 | grep -vzq "whatever means failure" 
}

if run_mongo; then
 echo "Worked!"
else
  echo "Failed!"
fi

如果您想避免读取整个输出,只需使用其他工具即可。以 Perl 为例:

mongo foo bar baz 2>&1 | perl -ne 'exit 1 if /whatever means failure/' 

答案2

如果您需要尽快终止:

run_mongo () {
    ! mongo foo bar baz 2>&1 | grep -q 'bad-pattern'
}

如果在输出中找到该模式,这将mongo尽快运行并终止该函数。bad-pattern当模式匹配时,grep立即退出,并mongo在尝试写入死管道时立即接收 PIPE 信号。

由于!,管道的退出状态将被反转,即,如果未找到模式,则退出状态为零;如果找到,则退出状态为非零。

如果您需要让其mongo完成写入输出:

run_mongo () {
    ! mongo foo bar baz 2>&1 | grep 'bad-pattern' > /dev/null
}

这与此答案中的第一段代码相同,但grep现在消耗mongo.

答案3

@terdon 的解决方案看起来不错,因为我是 Node.js 的粉丝,我只是写了一个这样的程序:

#!/usr/bin/env node

process.stdin.resume().once('data', function () {
   process.exit(1);
});

然后在我的 bash 脚本中有:

run_mongo(){
  mongo foo bar baz 2>&1
}

exit_if_match(){
    grep "$1" | "./node_modules/.bin/imminent_suicide"
}

run_mongo "foo" "bar" | exit_if_match "errmsg"

答案4

echo 'if stdout/stderr matches this' |
    awk '$0 ~ "if stdout/stderr matches this" { exit 1; }' ; echo $?

相关内容