bash 如何grep,排除一些模式?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18468716/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 00:07:13  来源:igfitidea点击:

How to grep, excluding some patterns?

bashgrep

提问by Loom

I'd like find lines in files with an occurrence of some pattern and an absence of some other pattern. For example, I need find all files/lines including loomexcept ones with gloom. So, I can find loomwith command:

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

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

Now, I want to search loomexcluding gloom. However, both of following commands failed:

现在,我想搜索loom排除gloom. 但是,以下两个命令都失败了:

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

What should I do to achieve my goal?

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

EDIT 1:I mean that loomand gloomare the character sequences (not necessarily the words). So, I need, for example, bloombergin the command output and don't need ungloomy.

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

EDIT 2:There is sample of my expectations. Both of following lines are in command output:

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

I faced the icons that loomedthrough the veil of incense.

Arty is sloomingin a gloomyday.

我面对着透过香火的面纱若隐若现的圣像。

阴沉的日子里,Arty隐隐约约

Both of following lines aren't in command output:

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

It's gloomyin'ower terrible — great muckle doolders o' cloods.

In the south west round of the heigh pyntit hall

这是gloomyin'奥尔可怕的-伟大的穆doolders O” cloods。

在 heigh pyntit 大厅的西南角

回答by houbysoft

How about just chaining the greps?

仅仅链接greps怎么样?

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

回答by Bentoy13

Another solution without chaining grep:

另一个没有链接的解决方案grep

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

Between brackets, you exclude the character gbefore any occurrence of loom, unless loomis the first chars of the line.

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

回答by Sam

A bit old, but oh well...

有点旧,但哦,好吧...

The most up-voted solution from @houbysoft will not work as that will exclude any line with "gloom" in it, even if it has "loom". According to OP's expectations, we need to include lines with "loom", even if they also have "gloom" in them. This line needs to be in the output "Arty is slooming in a gloomy day.", but this will be excluded by a chained grep like

来自@houbysoft 的投票最多的解决方案将不起作用,因为它会排除任何带有“gloom”的行,即使它有“loom”。根据 OP 的期望,我们需要包含带有“loom”的线条,即使它们也带有“gloom”。这一行需要在输出“Arty is slooming in a grey day.”中,但这将被链接的grep排除在外

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

Instead, the egrep regexexample of Bentoy13works better

相反,Bentoy13egrep regex示例效果更好

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

as it will include any line with "loom" in it, regardless of whether or not it has "gloom". On the other hand, if it only has gloom, it will not include it, which is precisely the behaviour OP wants.

因为它将包含任何带有“loom”的行,无论它是否具有“gloom”。另一方面,如果它只有阴暗,则不会包括它,这正是 OP 想要的行为。

回答by Ed Morton

Just use awk, it's much simpler than grep in letting you clearly express compound conditions.

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

If you want to skip lines that contains both loomand gloom:

如果要跳过同时包含loomand 的行gloom

awk '/loom/ && !/gloom/{ print FILENAME, FNR, 
awk '/(^|[^g])loom/{ print FILENAME, FNR, 
awk '/\<loom\>/{ print FILENAME, FNR, 
grep -vn "gloom" `grep -l "loom" ~/projects/**/trunk/src/**/*.@(h|cpp)`
}' ~/projects/**/trunk/src/**/*.@(h|cpp)
}' ~/projects/**/trunk/src/**/*.@(h|cpp)
}' ~/projects/**/trunk/src/**/*.@(h|cpp)

or if you want to print them:

或者如果你想打印它们:

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

and if the reality is you just want lines where loomappears as a word by itself:

如果现实是你只想要单独loom出现作为一个词的行:

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

回答by Oleg Kokorin

-vis the "inverted match" flag, so piping is a very good way:

-v是“反向匹配”标志,因此管道是一个非常好的方法:

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

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

回答by Juto

/*You might be looking something like this?

/*你可能看起来像这样?

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

The BACKQUOTES are used like brackets for commands, so in this case with -lenabled, the code in the BACKQUOTES will return you the file names, then with -vn to do what you wanted: have filenames, linenumbers, and also the actual lines.

BACKQUOTES 就像命令的括号一样使用,因此在这种情况下-l启用后,BACKQUOTES 中的代码将返回文件名,然后使用 -vn 执行您想要的操作:包含文件名、行号以及实际行。

UPDATEOr with xargs

更新或使用 xargs

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

Hope that helps.*/

希望有所帮助。*/

Please ignore what I've written above, it's rubbish.

请忽略我上面写的,这是垃圾。

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

回答by anubhava

You can use grep -P(perl regex) supported negative lookbehind:

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

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

I added \bfor word boundaries.

我添加\b了单词边界。

回答by Jiminion

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

回答by Tiborcz Kiss

Simply use! grep -vmultiple times.

简单使用!grep -v多次。

Content of file

文件内容

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

Exclude the line or match

排除行或匹配

##代码##

Exclude the line or match multiple

排除该行或匹配多个

##代码##

回答by Abhinandan

Question: search for 'loom' excluding 'gloom'.
Answer:

问题:搜索不包括 'gloom' 的 'loom'。
回答:

##代码##