tags:

views:

394

answers:

5

When using grep --color=always I can get pretty color highlighting for regex matches.

However, grep only returns lines with at least one match. Instead, I am looking for a way to simply highlight regex matches, while leaving all other input alone, without dropping lines without any matches.

I have tried to get color working with sed, and read the grep documentation, but I can't seem to get what I want.

In case my description isnt obvious, I want:

INPUT:

  • fred
  • ted
  • red
  • lead

Regex:

  • ".*red"

OUTPUT:

  • fred ( in red )
  • ted
  • red ( in red )
  • lead

So that I could do:

list_stuff | color_grep "make_this_stand_out_but_dont_hide_the_rest"

EDIT:

I have found a solution, which isn't pretty, but it works:

Thanks to: http://www.pixelbeat.org/docs/terminal_colours/

Particularly the script (which I modified/simplified): http://www.pixelbeat.org/talks/iitui/sedgrep

function sedgrep ()
{
    C_PATT=`echo -e '\033[33;01m'`
    C_NORM=`echo -e '\033[m'`

    sed -s "s/$1/${C_PATT}&${C_NORM}/gi"
}

Still looking for an easier way to do this!

+1  A: 

This little function works well in my ZShell:

function color_grep {
    sed s/$1/$fg[yellow]$1$terminfo[sgr0]/g
}

(Needs

autoload colors zsh/terminfo

)

Maybe you can do something similar?

Edit: Sorry, this won't work with regexes. You will have to tweak it a bit ...

boxxar
I am using bash, but that looks to be nearly the same type of solution as the one I posted. Thanks!
michalmocny
+1  A: 

The way you're doing this now is probably about as clean as you can expect to make this, unless of course you write your own grep tool. If you don't necessarily care about preserving the order of the output, here's the other way I can think of to do this:

function colormatch ()
{
    tee - | grep --color=always $1 | sort | uniq
}

Not as efficient as using sed (more processes created, and tee-ing the output), so I'd probably recommend sticking with your sed solution.

Jay
Good point. Your solution has a syntax which is easier to remember, for those times when I don't have my .bashrc file handy :)
michalmocny
+2  A: 

You could use the -C<num> option to grep which shows you <num> lines of context around your match. Just make sure <num> is as least as large as the number of lines in your file.

PiedPiper
oooh, clever abuse of the context option, I like it :-)
Jay
Actually, I tried this, and it didnt work for three reasons:One, if their was not a single match, it wouldnt return anything.Two, it was slow when <num> was really large.Three (biggest problem), results get printed with each "match", so if I am running this command on a pipe I get output in blobs
michalmocny
However, it is a very clever way to do it as a quick hack, especially for small results if you know their is a hit :)I do this all the time when not on my own PC
michalmocny
A: 

I recently made something similar as a filter. I use it to color the "headers" in a tail with multiple files, like this:

tail -f access.log error.log foo.log | logcol.sh

The headers look like this:

==> access.log <==

I got confused by the quick changes between the different logfiles, so this logcol.sh helps. The ==> is hardcoded for the specific usage but could be a parameter as well.

#!/bin/sh
while read line
do
  if test `expr "$line" : "==>.*"`  -eq 0 ;
  then
    printf '\033[0m%s\n' "$line"
  else
    printf '\033[0;31m%s\n' "$line"
  fi
done

Maybe not the most elegant but I think it's quite readable. I hope I don't have any typos ;-) HTH, rob

A: 

I'm digging this little python utility. If not on debian, use alien to convert to rpm.

http://korpus.juls.savba.sk/~garabik/software/grc.html

regexp=.*red
colours="\033[38;5;160m"
count=once

This is a nice page on terminal colors.

http://www.pixelbeat.org/docs/terminal_colours/

(Queen's english is so colourful.)

TJ