显示所有行的grep,而不仅仅是匹配的行,设置退出状态。

9
我正在将某个命令的输出导入到egrep中,以确保特定的失败字符串不会出现。
很遗憾,该命令本身在失败时无法返回正确的非零退出状态,这就是我这样做的原因。
command | egrep -i -v "badpattern"

这个命令可以给我所需要的退出码(如果输出中出现了badpattern则为1,否则为0),但是它只会输出那些不匹配模式的行(因为-v开关就是设计成这样的)。对于我的需求,那些行才是最有趣的行。
是否有一种方法可以让grep盲目地通过所有输入行,并根据需要给我退出码?
如果没有,我想我可以使用perl -ne "print; exit 1 if /badpattern/"。我使用-n而不是-p,因为-p不会打印出有问题的行(因为它在运行完单行程序后再打印)。所以,我使用-n并自己调用print,这至少给了我第一个有问题的行,但是输出(和执行)会停在那里,所以我必须做一些类似于 perl -e '$code = 0; while (<>) { print; $code = 1 if /badpattern/; } exit $code'
的事情,这样就完成了整个过程,但是有点繁琐,是否有一个简单的命令行开关可以满足我的需求?
3个回答

7

实际上,你的 Perl 想法还不错。尝试使用以下代码:

perl -pe 'END { exit $status } $status=1 if /badpattern/;'

我敢打赌,这至少和其他被建议的选项一样快。

很酷,比我的 Perl 一行代码还要短。 - hsiu

3
$ tee /dev/tty < ~/.bashrc | grep -q spam && echo spam || echo no spam

所以,最后一部分是不必要的,但第一部分有时候有效。我不理解这个,但如果我执行 echo badpattern | tee /dev/tty | grep -q -v badpattern,它有效。但是,如果我将“badpattern”与其他内容放在一个文件中,并执行 cat bpfile | tee /dev/tty | grep -q -v badpattern,它就无效了,退出状态总是返回0。所以,很难知道它是否适用于从curl(我正在使用的第一个命令)获取的内容。 - hsiu

1

你觉得重定向到 /dev/null 怎么样?这样就可以删除所有行,但仍然可以获得退出代码。

$ grep spam .bashrc > /dev/null

$ echo $?
1

$ grep alias .bashrc > /dev/null

$ echo $?
0

或者你可以直接使用-q开关

   -q, --quiet, --silent
          Quiet;   do   not  write  anything  to  standard  output.   Exit
          immediately with zero status if any match is found, even  if  an
          error  was  detected.   Also see the -s or --no-messages option.
          (-q is specified by POSIX.)

但是我确实想看到所有行。我不想过滤这些行,只想扫描它们,如果有匹配的内容,则将退出代码设置为非零值。但是所有行都应该被输出。 - hsiu
完全误解了您的问题,如果您知道输出的长度,可以像这样做:grep alias -A1000 -B1000,即显示匹配项上下1k行,即所有输出。 - Fredrik Pihl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接