5

How would I go about colorizing the output of tail with sed?

echo "`tput setaf 1`foo`tput op`" works as expected

echo "foo" | sed -e 's/(foo)/`tput setaf 1`\0`tput op`/g' however, does not.

What am I missing here?

Demian Brecht
  • 225
  • 3
  • 7
  • The reason it's not working is that backticks have no special meaning inside single quotes but they do have a special meaning inside double quotes. – Ladadadada Nov 23 '12 at 19:57
  • 1
    Take a look at http://unix.stackexchange.com/questions/8414/how-to-have-tail-f-show-colored-output - it has some suggestions for colorizing output including rainbow, multitail and grc which should suit your needs if grep does not. – syneticon-dj Nov 23 '12 at 22:58

2 Answers2

9

Does it have to be sed?

echo "foo bar baz" | grep --color=auto "bar"

The above will highlight bar in red by default. The man page says you can choose what colour to use with the environment variable GREP_COLORS.

To make it print all lines and only highlight bar:

echo "foo bar baz" | grep -E --color=auto "^|bar"
  • 1
    +1 use the right tool for the job - there is no need to rape sed just to colorize output. –  Nov 23 '12 at 20:41
  • @syneticon-dj: This doesn't actually work to colour the output of tail though. It will only print lines containing "bar" (with bar highlighted) and all other lines will be left unprinted. –  Nov 23 '12 at 20:45
  • @Iain adding -C <great number> should help as a quick hack –  Nov 23 '12 at 22:52
  • 1
    Not worth a whole new answer, but you can also just do: tail file | grep "pattern\|" or tail file | grep -E "pattern|", depending on your mood. ;) (Supposing you already have --color=auto in your COLOR_OPTIONS environment variable set) – DrBeco Nov 20 '17 at 03:43
  • Brilliant! tail -n 2 -f /usr/local/var/log/nginx/*.log & tail -n 5 -f /usr/local/var/log/*.log | grep --color=auto "]" – vintagexav Jul 20 '23 at 14:18
6

The backticks `` in the echo command spawn a process and it's output is substituted into the echo command line. You can see this with e.g.

echo "`tput setaf 1`" | hexdump -C
00000000  1b 5b 33 31 6d 0a                       |.[31m.|

This works because the contents of the "..." are expanded before being passed to echo.

The sed command you're using wraps everything in ' so it is passed to sed without expansion and sed sees it all as literal text.

You can fix this by putting "" around your sed command

echo "foo" | sed -e "s/\(foo\)/`tput setaf 1`\1`tput op`/g"

You also had an error in your sed command. The ( and ) need to be escaped \( and \) to denote the remembered pattern. I've also never use \0 I've always used \1 as the first remembered pattern.