Reputation: 9986
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 loom
except ones with gloom
. So, I can find loom
with command:
grep -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp)
Now, I want to search loom
excluding gloom
. However, both of following commands failed:
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 loom
and gloom
are the character sequences (not necessarily the words). So, I need, for example, bloomberg
in the command output and don't need ungloomy
.
EDIT 2: There is sample of my expectations. Both of following lines are in command output:
I faced the icons that loomed through the veil of incense.
Arty is slooming in a gloomy day.
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
Upvotes: 109
Views: 315907
Reputation: 65
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
Upvotes: 6
Reputation: 2672
-v
is the "inverted match" flag, so piping is a very good way:
grep "loom" ~/projects/**/trunk/src/**/*.@(h|cpp)| grep -v "gloom"
Upvotes: 7
Reputation: 11
Question: search for 'loom' excluding 'gloom'.
Answer:
grep -w 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp)
Upvotes: 0
Reputation: 309
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.
Upvotes: 12
Reputation: 1276
/*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
Upvotes: 5
Reputation: 203129
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)
Upvotes: 9
Reputation: 4956
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.
Upvotes: 27
Reputation: 784898
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.
Upvotes: 4
Reputation: 5168
grep -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp) | grep -v 'gloom'
Upvotes: 3
Reputation: 33392
How about just chaining the greps?
grep -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp) | grep -v 'gloom'
Upvotes: 133