如何grep,排除某些模式?


84

我想在文件中查找出现某种模式而没有某种其他模式的行。例如,我需要找到所有文件/行,包括loom带有的文件/行gloom。所以,我可以loom用命令找到:

grep -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp)

现在,我要搜索loom排除gloom。但是,以下两个命令均失败:

grep -v 'gloom' -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp)
grep -n 'loom' -v 'gloom' ~/projects/**/trunk/src/**/*.@(h|cpp)

我应该怎么做才能实现自己的目标?

编辑1:我的意思是loomgloom是字符序列(不一定是单词)。因此,例如,我需要bloomberg在命令输出中,不需要ungloomy

编辑2:有我的期望的样本。以下两行都在命令输出中:

我面对着穿过香气笼罩的标志。

附庸风雅的slooming在一个阴沉的一天。

以下两行均不在命令输出中:

这是令人沮丧的令人沮丧的阴毛–伟大的穆勒杜勒犬或血栓。

在高皮特特大厅的西南圆


您是否正在寻找符合条件的文件?
Juto 2013年

我正在寻找行符合我的条件的文件。我想查看所有集的列表文件名+匹配行数+匹配行本身。
织布机

如果该行是there is a loom in the gloom-您是否要打印该行?只是想了解您是否只是在寻找发生织机而不是作为织机的一部分的行,或者您是否确实想排除包含织机的行,即使织机自己出现在行的其他位置。发布一些样本输入和预期输出将有所帮助。
Ed Morton

所以你的问题是真的How do I find lines containing the string "loom" where "loom" is not preceded by the letter "g"吗?如果您发布了一些示例输入和所需的输出,将会有很大帮助。该问题的答案包含在下面的答案中。
Ed Morton

1
@EdMorton -是的,你说得对-我需要的所有线路,其中发生loom不前g。(对不起。我昨天开始发表评论,但从未完成。这条评论是偶然发送的。)
织布机

Answers:


102

只是链状的抓钩怎么样?

grep -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp) | grep -v 'gloom'

13
准时。完美的作品。-v是要排除的选项。谢谢
Ravi Krishna P

2
来自问题的答案:因此,例如,我需要bloomberg在命令输出中,而不需要ungloomy 如果一行包含“ ...,而Bloomberg对前景不满意...”,则可以删除该行,但是需要它(因为如果包含bloomberg)。
乔纳森·勒夫勒

23

无需链接的另一种解决方案grep

egrep '(^|[^g])loom' ~/projects/**/trunk/src/**/*.@(h|cpp)

在方括号之间,除非g出现该行的第一个字符loom,否则您将在出现任何字符之前排除该字符loom


9

有点老了,但是哦...

@houbysoft投票最多的解决方案将不起作用,因为它将排除其中包含“阴沉”的任何行,即使该行包含“ loom”也是如此。根据OP的期望,即使行中也包含“ gloom”,我们也需要包括“ loom”行。该行必须在输出“ Arty在阴沉的日子里不断涌现。”,但是这将被链接的grep排除,例如

grep -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp) | grep -v 'gloom'

相反,Bentoy13egrep regex示例效果更好

egrep '(^|[^g])loom' ~/projects/**/trunk/src/**/*.@(h|cpp)

因为它将包含其中任何带有“织机”的行,无论它是否具有“阴沉”。另一方面,如果它仅具有暗淡,它将不包括暗淡,这恰恰是OP想要的行为。


8

只需使用awk,它就比grep简单得多,可以让您清楚地表达复合条件。

如果要跳过包含loom和的行gloom

awk '/loom/ && !/gloom/{ print FILENAME, FNR, $0 }' ~/projects/**/trunk/src/**/*.@(h|cpp)

或者如果您要打印它们:

awk '/(^|[^g])loom/{ print FILENAME, FNR, $0 }' ~/projects/**/trunk/src/**/*.@(h|cpp)

如果实际情况是,您只希望线条loom本身作为单词出现:

awk '/\<loom\>/{ print FILENAME, FNR, $0 }' ~/projects/**/trunk/src/**/*.@(h|cpp)

3
考虑一下如何编写grep命令以获取包含abc和的行defghi以任意顺序)。现在将其与进行比较awk '/abc/ && /def/ && /ghi/'。现在考虑awk '/loom/ && !/gloom/'在此页面的答案中如何编写等效于grep的内容。
Ed Morton 2013年

我对awk不太熟悉,显然有关于此命令的书籍。就目前而言,我对grep表示满意,也许有一天我会说出与您相同的内容。:)
Juto

2
awk是用于处理文本文件的标准UNX工具(即,在所有UNIX安装中均可用)。这就是发明的目的,并且非常擅长。如果您使用的是UNIX并分析文本文件,请从Arnold Robins的《有效Awk编程》第三版中学习awk。与awkscondition { action }语法相关的范式有一个小的转变,但是对于任何具有C或其他基于Algol的语言经验的人来说,这都是轻而易举的事情。
Ed Morton 2013年

奖金:输出类似grep -Hn --colorawk '/loom/ && !/gloom/ { gsub(/loom/, color("1;31") "&" color(0)); print color(35) FILENAME color(36) ":" color(32) FNR color(36) ":" color(0) $0; }; function color(c) { return "\033[" c "m"; }'
纠结


5

/ *您可能正在寻找类似的东西?

grep -vn "gloom" `grep -l "loom" ~/projects/**/trunk/src/**/*.@(h|cpp)`

BACKQUOTES的用法类似于命令的括号,因此在-l启用此情况下,BACKQUOTES中的代码将返回文件名,然后使用-vn执行您想要的操作:具有文件名,行号以及实际行。

更新或使用xargs

grep -l "loom" ~/projects/**/trunk/src/**/*.@(h|cpp) | xargs grep -vn "gloom"

希望能有所帮助。* /

请忽略我上面写的东西,那是垃圾。

grep -n "loom" `grep -l "loom" tt4.txt` | grep -v "gloom"

               #this part gets the filenames with "loom"
#this part gets the lines with "loom"
                                          #this part gets the linenumber,
                                          #filename and actual line

4

您可以使用grep -P(perl regex)支持negative lookbehind

grep -P '(?<!g)loom\b' ~/projects/**/trunk/src/**/*.@(h|cpp)

我添加\b了单词边界。


2
您不需要回头,就\([^g]\|^\)可以了。而且这并不排除同时包含loom和的行gloom
凯文

@Kevin:OP想用织布机找到线,但是not gloom
anubhava 2013年

究竟。如果某行同时包含这两个行,则他将不希望这样做,但是无论如何它将与之匹配。
凯文

@Kevin:这不会匹配暗淡,但是会匹配暗淡(如OP所希望的)。
anubhava 2013年

来自问题的答案:因此,例如,我需要bloomberg在命令输出中,而不需要ungloomy 因此,单词边界适得其反。
乔纳森·勒夫勒

3
grep -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp) | grep -v 'gloom'

来自问题的答案:因此,例如,我需要bloomberg在命令输出中,而不需要ungloomy 如果一行包含“ ...,而Bloomberg对前景不满意...”,则可以删除该行,但是需要它(因为如果包含bloomberg)。
乔纳森·勒夫勒

@JonathanLeffler“我需要找到所有文件/行,包括织机,只有那些带有织机的文件/行。”
Jiminion

3

只需使用!grep -v多次。

文件内容

[root@server]# cat file
1
2
3
4
5

排除行或匹配

[root@server]# cat file |grep -v 3
1
2
4
5

排除行或匹配多个

[root@server]# cat file |grep -v 3 |grep -v 5
1
2
4

0

问题:搜索“ loom”(不包括“ gloom”)。
回答:

grep -w 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp)

1
来自问题的答案:因此,例如,我需要bloomberg在命令输出中,而不需要ungloomy 我认为这-w不是解决这个难题的方法。
乔纳森·莱夫勒
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.