Grep output with multiple Colors?

BashColorsSedAwkGrep

Bash Problem Overview


Is there an elegant method in bash for running grep against a text file with two or more patterns, and each pattern that matches is output in a different color?

So a line that matches on MALE and AUGUST would output MALE in blue and AUGUST in orange? I am open to the use of sed, awk, grep and crayons or others.

Bash Solutions


Solution 1 - Bash

You can cascade greps with different colors by specifying --color=always and using the regular expression 'foo|$' to pass all lines.

For example:

tail -f myfwlog | GREP_COLOR='01;36' egrep --color=always 'ssh|$' | GREP_COLOR='01;31' egrep -i --color=always 'drop|deny|$'

If you want the entire line to be highlighted, update your regular expression accordingly:

.... GREP_COLOR='01;31' egrep -i --color=always '^.*drop.*$|^.*deny.*$|$'

Solution 2 - Bash

grep is a regular expression matcher, not a syntax highlighter :). You'll have to use multiple invocations of grep, using a different value of GREP_COLOR for each.

GREP_COLOR="1;32" grep foo file.txt | GREP_COLOR="1;36" grep bar

That would highlight "foo" and "bar" in different colors in lines that match both. I don't think there is a (simple) way to handle all occurrences of either pattern, short of merging the output stream of two independent calls:

{ GREP_COLOR="1;32" grep foo file.txt
  GREP_COLOR="1;36" grep bar file.txt
} | ...

which will obviously look different than if there were a way to assign a separate color to each regular expression.


You can use awk to substitute each match with itself wrapped in the correct control code.

 echo "foo bar" | awk '{ gsub("bar", "\033[1;33m&\033[0m");
                         gsub("foo", "\033[1;36m&\033[0m"); print }'

In each line, you globally replace anything matching the given regular expression with itself (&) wrapped in the ANSI escape sequences for desired color (which grep --color does for you). After processing all of the possible matches, you need to explicitly print the line.

Solution 3 - Bash

If you want something out of the box, you're probably looking for hhighlighter.

Here's an example:JBoss output

Take a look. It's incredibly useful for coloring words in different colors automatically. It's an impressive project that's built on top of ack.

Solution 4 - Bash

I had the need to highlight strings in text files, and did not find a way that suited my needs, so I wrote a simple C program to colorize strings matching regular expressions.

You can download the source code from GitHub :

git clone http://github.com/mbornet-hl/hl

then :

cd hl/cr; make

Here is the usage :

hl: version 1.21
Usage: hl [-h|-eidD][-E][-rgybmcwRGYBMCW] regexp ...
  -h : help
  -v : version
  -u : do not bufferize output on stdout
  -e : extended regular expressions
  -i : ignore case
  -E : print on stderr
  -r : red
  -g : green
  -y : yellow
  -b : blue
  -m : magenta
  -c : cyan
  -w : white
  -R : red     (reverse video)
  -G : green   (reverse video)
  -Y : yellow  (reverse video)
  -B : blue    (reverse video)
  -M : magenta (reverse video)
  -C : cyan    (reverse video)
  -W : white   (reverse video)
  -d : debug
  -D : display regular expressions

To colorize the word "red" in red, and the word "blue" in blue, you just have to type in the following command :

echo "red blue red blue" | hl -r red -b blue

and here is an example to highlight the output of the ifconfig command :

hl -ei -m '^(eth|(vir)?br|vnet)[0-9.]*:[0-9]+\>'             \
       -b '^(eth|(vir)?br|vnet)[0-9.]*\.[0-9]+\>'            \
       -c '([0-9a-f]{2}:){5}[0-9a-f]{2}'                     \
       -g '\<UP\>|\<RUNNING\>|([0-9]{1,3}\.){3}[0-9]{1,3}\>' \
       -y '^(eth|(vir)?br|vnet)[0-9.:]*\>'                   \
       -W '[0-9a-f]{4}::[0-9a-f]{4}\:[0-9a-f]{4}:[0-9a-f]{4}:[0-9a-f]{4}' \
       -r ' (errors|dropped|overruns):[^0][0-9]*'

The order in which you specify the colors is important : if a string matches several regular expressions, the 1st one as a higher priority than the 2nd one, the 2nd one as a higher priority than the 3rd one, and so on ...

Hope This Helps.

Solution 5 - Bash

Try the wonderful rpen http://github.com/rtulke/rpen

require egrep or grep

Now you need to copy the rpen.py file into the right folder and give it appropraite rights

cp rpen.py /usr/local/bin/rpen
chmod a+rx /usr/local/bin/rpen

then try

ps xau |rpen Ss "S\+" "\?\?" 

Solution 6 - Bash

So here's the version(s) using sed. Let's say you want the word "FAILED" to be colored red, that would be:

sed 's/\(ERROR\)/\o033[31m\1\o033[39m/'

To have the whole line containing the word "FAILED" marked in red:

sed 's/\(.*ERROR.*\)/\o033[31m\1\o033[39m/'

To have multiple words marked red:

sed 's/\(ERROR\|FAILED\)/\o033[31m\1\o033[39m/'

To have multiple words and their wohle lines marked in red:

sed 's/\(.*FAILED.*\|.*ERROR.*\)/\o033[31m\1\o033[39m/'

To have multiple colors (ERROR=red/FAILED=blue)

sed -e 's/\(ERROR\)/\o033[31m\1\o033[39m/' -e 's/\(FAILED\)/\o033[34m\1\o033[39m/'

To use all this over ssh:

ssh user@host -t "tail -n 1024 -f /some/log/file | sed --unbuffered -e 's/\(.*ERROR.*\|.*FAILED.*\)/\o033[31m\1\o033[39m/' -e 's/\(.*postfix.*\|.*dhcpd.*\)/\o033[32m\1\o033[39m/'"

And for not having to type this everytime, just declare it as a function in your bashrc.

For other colors look up ANSI codes.

Solution 7 - Bash

How about this? You can do it with grep ONLY! Tricks here are (1) you take /OR/ of the words you are searching; (2) you use -A and -B options with large enough numbers (larger then the line count of your file).

echo "you make it" > tmp
echo "you take it" >> tmp
echo "you cake it" >> tmp
echo "you bake it" >> tmp
echo "you wake it" >> tmp

GREP_COLOR='1;32' grep -P "(take|cake|bake)" --color=always tmp | GREP_COLOR='1;33' grep -P "(cake|bake)" --color=always -A10000 -B10000 | GREP_COLOR='1;34' grep -P "(bake)" --color=always -A10000 -B10000 

Solution 8 - Bash

cxpgrep is right for this purpose - highlight patterns in different colors.

cxpgrep 'PAT1|PAT2|...' FILE_OR_DIRECTORY

Solution 9 - Bash

My answer is below:

tailf logfile awk '/MALE/' {print "\033[34m" $0 "\033[39m"}  '/MALE/' {print "\033[33m" $0 "\033[39m"}

Solution 10 - Bash

you can use bline (Beautiful Line Output) specifically designed for complex output and colorizing.

all lines, foreground red:

ls | bline -a red

all lines, foreground red, background green:

ls | bline -a red:green

all lines, foreground is default (NOTE.3), background is green:

ls | bline -a :green

add color-mode, odd lines (foreground) will be in light,italic,red

ls | bline -o light:red

add text-mode, as well

ls | bline -o light:italic:cross:red

combine options are okay:

ls | bline -a light:green -i red -I 7 -r yellow -R 5-10

using hex value, foreground in red

df | bline -H -a ff00ff

hex, foreground green, background red

df | bline -H -a 00ff00:ff0000

hex just background

df | bline -H -a :ffff00

look for string: 'sda' and make that/those line(s) green

lsblk | bline -m sda light:green

some screenshots

enter image description here

enter image description here

enter image description here

enter image description here

enter image description here

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionEvil GeniusView Question on Stackoverflow
Solution 1 - BashRob WindsorView Answer on Stackoverflow
Solution 2 - BashchepnerView Answer on Stackoverflow
Solution 3 - BashEhtesh ChoudhuryView Answer on Stackoverflow
Solution 4 - BashBushView Answer on Stackoverflow
Solution 5 - BashcrayView Answer on Stackoverflow
Solution 6 - BashmikeymouseView Answer on Stackoverflow
Solution 7 - Bashuser22097View Answer on Stackoverflow
Solution 8 - BashtreulzView Answer on Stackoverflow
Solution 9 - BashRamin IsmayilliView Answer on Stackoverflow
Solution 10 - BashShakiba MoshiriView Answer on Stackoverflow