使用grep进行负匹配(不包含foo的匹配行)


988

我一直在尝试找出此命令的语法:

grep ! error_log | find /home/foo/public_html/ -mmin -60

要么:

grep '[^error_log]' | find /home/baumerf/public_html/ -mmin -60

除了名为的文件,我需要查看所有已修改的文件error_log

我在这里读过它,但是只发现了一个not-regex模式。


13
[^ error_log]永远都不会工作,[]是char类,一般来说regexp都不擅长否定模式(除非引擎实现了负先行)。
Jaap

Answers:


1753

grep -v 是你的朋友:

grep --help | grep invert  

-v,--invert-match选择不匹配的行

还请检查相关内容-L(的补充-l)。

-L,--files-without-match仅打印不包含匹配项的文件名


124
值得一提的是,-e可以使用多个(负)比赛选项:grep -v -e 'negphrase1' -e 'negphrase2'
Babken Vardanyan 2014年

31
类似于@ Babken-Vardanyan的评论也-能够使用管道来加入多个比赛,例如grep -v 'negphrase1|negphrase2|negphrase3'
Nicholas Adams

13
最后的评论与之前的评论不同,它将搜索两个都不匹配的内容。即,如果它匹配一个但不匹配另一个,则仍然打印。使用非相似的字符串尝试两种方式
Evan Langlois

7
@EvanLanglois-迫使grep使用-E作品将模式解释为扩展的正则表达式,即 grep -vE 'negphrase1|negphrase2|negphrase3'
Zlemini

1
@OlleHärstedt,我想我在之前的评论中误解了您的情况,以下可能是您想要的grep "" /dev/null * | grep foo | grep -v bar | cut -d: -f1 | sort -u为什么要使用第一个grep?总是有一种方法:))
Motti

139

您还可以将其awk用于这些目的,因为它可以使您以更清晰的方式执行更复杂的检查:

行不包含foo

awk '!/foo/'

行既不包含foo也不包含bar

awk '!/foo/ && !/bar/'

既不含线foo也不bar含有任一foo2bar2

awk '!/foo/ && !/bar/ && (/foo2/ || /bar2/)'

等等。


2
这真的很酷。您甚至不必学习完整的awk语言即可将regexp与逻辑运算符分组。感谢您的回答!
彼得T.

1
正是我想要的,非常感谢。
mmrs151 '19

13

在您的情况下,您大概不想使用grep,而是在find命令中添加一个负子句,例如

find /home/baumerf/public_html/ -mmin -60 -not -name error_log

如果要在名称中包含通配符,则必须对其进行转义,例如,排除后缀为.log的文件:

find /home/baumerf/public_html/ -mmin -60 -not -name \*.log
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.