87

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

| improve this question | |
  • Are you looking for files that match your criteria of lines that match your criteria? – Juto Aug 27 '13 at 14:50
  • I'm looking for files with lines matching my criteria. And I want to see list of all sets filename + number of matching line + matching line itself. – Loom Aug 27 '13 at 14:56
  • If the line was there is a loom in the gloom - would you want that line printed? Just trying to understand if you're just looking for lines where loom occurs other than as part of gloom or if you really do want to exclude lines containing gloom even when loom appears on it's own elsewhere on the line. Posting some sample input and expected output would help. – Ed Morton Aug 28 '13 at 3:44
  • So your question is really How do I find lines containing the string "loom" where "loom" is not preceded by the letter "g"? If you'd posted some sample input and desired output that would have helped a lot. The answer to that question is included in the answers below. – Ed Morton Aug 30 '13 at 11:38
  • 1
    @EdMorton - Yes, you're right - I need all lines, where occurs loom without preceded g. (I'm sorry. I started to comment yesterday, but never finished. Accidentally this comment was sent.) – Loom Aug 30 '13 at 12:02

10 Answers 10

104

How about just chaining the greps?

grep -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp) | grep -v 'gloom'
| improve this answer | |
  • 13
    Just in time. Works Perfectly. -v is the option to exclude. Thanks – Ravi Krishna P Dec 16 '14 at 17:03
  • 2
    From the question: So, I need, for example, bloomberg in the command output and don't need ungloomy. If a single line contained '… and bloomberg is ungloomy about the prospects…', you would eliminate that line but it is wanted (because if contains bloomberg). – Jonathan Leffler Jun 27 '17 at 14:53
23

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.

| improve this answer | |
9

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.

| improve this answer | |
8

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)
| improve this answer | |
  • 3
    Think about how you'd write a grep command to get lines that contain abc and def and ghi in any order. Now compare that to awk '/abc/ && /def/ && /ghi/'. Now think about how the grep equivalent of awk '/loom/ && !/gloom/' is being written in the answers on this page. – Ed Morton Aug 28 '13 at 12:19
  • I am not very familiar with awk, apparently there are books about this command on its own. For now I am fine with grep, maybe one day I will say the same thing you did. :) – Juto Aug 28 '13 at 12:21
  • 2
    awk is THE standard UNX tool (i.e. available on ALL UNIX installations) for processing text files. That's what it was invented to do and it's very good at it. If you're on UNIX and parsing text files, learn awk from the book Effective Awk Programming, Third Edition by Arnold Robins. There's a small paradigm shift to get over related to awks condition { action } syntax but then it's a breeze for anyone with any C or other Algol-base language experience. – Ed Morton Aug 28 '13 at 14:11
  • Bonus: output like grep -Hn --color: awk '/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"; }' – tangle Nov 14 '18 at 4:22
6

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

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

| improve this answer | |
5

/*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
| improve this answer | |
4

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.

| improve this answer | |
3
grep -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp) | grep -v 'gloom'
| improve this answer | |
  • From the question: So, I need, for example, bloomberg in the command output and don't need ungloomy. If a single line contained '… and bloomberg is ungloomy about the prospects…', you would eliminate that line but it is wanted (because if contains bloomberg). – Jonathan Leffler Jun 27 '17 at 14:51
  • @JonathanLeffler "I need find all files/lines including loom except ones with gloom." – Jiminion Jun 27 '17 at 15:11
3

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 |grep -v 5
1
2
4
| improve this answer | |
0

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

grep -w 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp)
| improve this answer | |
  • 1
    From the question: So, I need, for example, bloomberg in the command output and don't need ungloomy. I don't think that -w is the solution to that conundrum. – Jonathan Leffler Jun 27 '17 at 14:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.