如何抓取,排除一些模式?

我希望在文件中找到出现了某种模式而没有其他模式的行。例如,我需要查找包括 loom在内的所有文件/行,除了那些具有 gloom的文件/行。因此,我可以通过命令找到 loom:

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

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

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: 这是我期望的样本。 以下两行都在命令输出中:

我透过香的面纱面对着 隐约可见的图标。

阿蒂在 阴郁的日子里是 缓缓移动

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

这是 忧郁的心情电力可怕的ーー伟大的马克涂鸦者 o’cloods。

在西南方向的高山丘陵大厅里

282127 次浏览

How about just chaining the greps?

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

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

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

I added \b for word boundaries.

Another solution without chaining grep:

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

Between brackets, you exclude the character g before any occurrence of loom, unless loom is the first chars of the line.

/*You might be looking something like this?

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

The BACKQUOTES are used like brackets for commands, so in this case with -l enabled, 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.

UPDATE Or with xargs

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

Hope that helps.*/

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

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

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

If you want to skip lines that contains both loom and gloom:

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

or if you want to print them:

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

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

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

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

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

Instead, the egrep regex example of Bentoy13 works better

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.

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

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

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

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

Simply use! grep -v multiple times.

#Content of file

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

#Exclude the line or match

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

#Exclude the line or match multiple

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