如果没有匹配,grep会返回0

35

有没有一种bash脚本,可以使用grep命令返回结果为true?

例如:在我的CF日志中有1000条103.12.88记录。如果检测到1个或多个结果,能否进行grep 103.12.88操作并打印/输出结果,显示YES或True。


我曾尝试过这个,但最终结果是:value=$( grep -ic "210.64.203" /var/logs ) if [ $value -eq 1 ] then echo "我找到了210.64.203"结果出现了 第2行:[: 参数太多 - julian lee
2
这个问题的标题有点奇怪。如果没有匹配,通常应该被视为失败,因此返回0是不合适的。实际上,如果匹配成功,grep会返回0,否则返回非零值。 - William Pursell
嗨,William,实际上,如果没有找到结果,我更喜欢有一个输出。 所以,我认为“0”表示“否定/错误”。 - julian lee
2
因此我的评论是,在shell中0表示成功,非零表示失败。这是一个重要的约定。 - William Pursell
你好,William,收到,谢谢! - julian lee
1
由于问题的标题没有改变,我认为对于那些正在寻找答案的人来说,回答那个特定的问题非常重要。而答案很简单:grep -v可以做到。我将发布一个单独的答案。 - vp124
6个回答

52

这个问题的实际答案是在命令的末尾添加|| true,例如:

echo thing | grep x || true

这仍然会输出0返回代码。


10
不,它并不会产生任何输出,只是强制返回0。尝试使用ret=$( echo thing | grep x || true )ret=$( echo thing | grep -q x; echo $?; )进行比较。前者使$ret为空,而后者加载退出代码。也许你的意思是echo thing | grep x && echo true - Paul Hodges
1
不,我希望无论grep是否匹配(在这个示例中它不会),始终返回0返回代码。 - sebcoe
2
退出代码和输出是两个不同的东西。OP说:“如果检测到1个或多个结果,我能否使用grep 103.12.88,然后打印/输出结果显示YES或True”,这就是输出。您的解决方案很好,只是不能满足表述不清楚的OP的要求。 - Paul Hodges

6

虽然问题的标题有误导性,但由于它还没有被更改,我认为对于那些正在寻找答案的人来说,回答这个特定的问题很重要。而答案很简单:grep -v可以实现:它反转了退出代码。

$ echo thing | grep x -vqz
$ echo $?
0
$ echo thing | grep thing -vqz
$ echo $?
1


注意需要使用-z参数来将整个文件流作为一行处理;否则,在多行文件中,即使找到匹配项或没有找到匹配项,也会得到退出状态0。(-q标志只是用于抑制输出)
注:本文翻译的原出处链接为:https://unix.stackexchange.com/questions/433711/grep-exit-with-1-if-match

2
您正在错误地处理返回值。
value=$( grep -ic "210.64.203" /var/logs )

value设置为grep的输出,而不是其返回代码。

执行命令后,退出代码存储在$?中,但通常不需要它。

if grep -ic "210.64.203" /var/logs 
then echo "Found..."
else echo "not found"
fi

如果你想要取得数值,那么需要测试内容。
rec="$( grep -ic "210.64.203" /var/logs )"
if [ -n "$rec" ] ; then echo found; fi

如果使用bash,则可以:
if [[ "$rec" ]] ; then echo found; fi

虽然我更喜欢明确表达 -
if [[ -n "$rec" ]] ; then echo found; fi

1
与其写成 if [ ! "$rec" = "" ],一般来说更好的方式是写成 if [ -n "$rec" ] - William Pursell
修改过了。我在bash中总是和[[一起使用它,但由于我很少使用[,所以在测试时没有想到尝试它。谢谢。 - Paul Hodges

1
[user@host ~]$ cat ~/mylogfile.txt
no secrets here
[user@host ~]$ grepnot(){ ! grep $1 $2; return $?;}
[user@host ~]$ grepnot password mylogfile.txt 
[user@host ~]$ echo $?
0
[user@host ~]$ grepnot secret mylogfile.txt 
no secrets here
[user@host ~]$ echo $?
1

注意:我在Jenkins管道中使用“grepnot”。我的上一个答案使用了“1 - $?”来反转返回代码。但是那个解决方案仍然导致管道中的grep失败。上面的解决方案(借鉴了以前的“!”答案)可以与管道一起使用。


0

或者不继续,echo thing | grep x && exit 1 - Sam

-1

如果你想在 grep 没有找到匹配时返回成功,更容易的方法是取反其输出:

echo "Hello, World" | not grep -q "Friend" && echo "No match"

这将打印No match,因为在输出中未找到"Friend"。

echo "Hello, World" | not grep -q "Hello" && echo "No match"

这段代码不会输出任何内容,因为在输出中找到了was

请注意,我们使用了标志-q(如--quiet),因此grep不会写入输出,但如果找到匹配项,则以状态0退出。


11
这段脚本不能正常工作——bash中没有"not",而第二行确实会输出。你是在使用其他的shell吗? - lonix
1
既然你提到了,not 似乎是随 LLVM 一起安装的程序(我已经安装了)。我会尝试收集更多信息来更新我的答案,但感谢你注意到了这个问题。 - Telmo Trooper
我在想为什么它对我不起作用 :) - lonix
2
一个感叹号 ! 所起到的作用类似于反转程序中的 not 命令:它可以'反转'状态码。因此,! true 的退出状态码为 1,而 ! false 的退出状态码为 0。 - ob-ivan
@ob-ivan 我收到了“bash: !: command not found”的错误提示。 - undefined
1
@koppor 空格很重要。Bash将!:视为一个单独的标记,无法识别此命令,但! :是两个独立的标记:一个是"not",一个是"true"。 - undefined

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