12

I know how to grep 2 keywords using 1 command, but I can only manage to color one of them in output . Here is my command:

grep 'keyword1' file.log | grep 'keyword2'

Only keyword2 is highlighted. How can I make keyword1 highlighted at the same time ?

2 Answers 2

16

The grep command accepts a --color=always option, so you can use

grep 'keyword1' file.log --color=always | grep 'keyword2'

As gertvdijk points out, this command may be inefficient, but it will look for all lines that contain both keyword1 and keyword2. If you want to highlight them in different colors, you can use

grep 'keyword1' file.log --color=always | GREP_COLORS="mt=01;34" grep --color=always 'keyword2'

which will highlight keyword2 in blue. The mt part means that grep will highlight matching text using this CSI code, and 01;34 means "bold blue foreground on normal background".

8
  • 1
    +1 for detailed explanation and customization options for the use case!
    – gertvdijk
    Dec 31, 2012 at 3:26
  • Funny, when I try this with: grep -R --color=always keyword1. | grep keyword2 //only the first keyword is higlighted. How could I adapt your answer to work with recursive search? Nov 6, 2013 at 12:00
  • 1
    That's odd, grep -R --color=always keyword1 . | grep keyword2 should work. Are you redirecting the output again (such as by piping the second grep into less -R)? If so, you'll need to add --color=always to the second one also.
    – Daniel H
    Nov 14, 2013 at 3:55
  • Great answer! To highlight both, a --color=auto would be needed for the second grep, just after 'keyword2'.
    – Luis
    May 21, 2019 at 10:34
  • @Luis Yeah, you’re right that Grep at least often defaults to no color (although that might be a configure-time option? I don’t think I had that overridden in 2013 when it worked on my machine without that…). I added --color=always to the answer, because you might want to pipe it to less or something also.
    – Daniel H
    May 21, 2019 at 20:59
4

Try actual regular expressions, rather than piping to another instance of grep, e.g.:

grep -E "\<foo\>.*\<bar\>" file

This limits to matching lines in which this the keywords match in this order only, unfortunately. Anyway, the use of grep in your question is rather inefficient and you should avoid it. The answer of @DanielH is pretty much more straightforward for your case, probably.

For an 'or' matching of keywords, I use this regularly:

grep -E "(foo|bar)" file
3
  • 1
    I think that the OP wants only lines that contain both keywords (the command you gave gives all lines that contain either one).
    – Daniel H
    Dec 31, 2012 at 3:13
  • @DanielH Thanks for pointing that out. I've updated my answer.
    – gertvdijk
    Dec 31, 2012 at 3:20
  • Doesn't that still only work if foo comes before bar? I don't know if there's a better way than foo.*bar|bar.*foo, or if that is even necessary for this case (which appears to be a log file which would probably have a standard order for the keywords). I added my answer before you updated yours, but I'll keep it around in case there's a situation where chained greps really are necessary (or any other time colored output shouldn't be sent to the terminal, like grep | less -R).
    – Daniel H
    Dec 31, 2012 at 3:29

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .