Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I regularly use this command line but I would like to change the color of the "|" to green in the output. Does anyone know how I can accomplish this?

tail -f file.log  | tr '\001' '|' | grep TEST
share|improve this question

4 Answers 4

up vote 3 down vote accepted

I don't think you can with tr because the replacement set is truncated to the length of the match set, and changing color requires some control characters.

Not impossible with sed tho:

tail -f file.log  | sed s/a/\\x1b[32m\|\\x1b[0m/g

1b is hex for octal 33, oft seen in things like color prompts because the shell likes octal (but to get "unprintable" control characters through sed, use hex). E.g., to just print a green bar:

echo -e "\033[32m|\033[0m"

The control sequences are "ANSI escape sequences", see here for details (32 is green foreground, 0 is reset). Octal 33 = decimal 27 = the ASCII 'ESC' character, hence "escape sequence".

share|improve this answer
tail -f file.log  | sed -n '/TEST/s/\x1/\x1b[32m|\x1b[0m/gp'
  • -n tell sed to suppress the output by default (but the final p will tell to print the matched rows, a sort of grep)
  • /TEST/ select only lines that match (as grep)
  • s to replace \x1 (\x is the shell escape for hexadecimal values) with \x1b[32m|\x1b[0m.
    • \x1b[ start an ANSI escape code
    • 32 is the color green for the foreground text
    • \x1b[0m reset the foreground color
    • g for global, replace very occurrence

You may set it in your .bashrc as a function (not tested)

loggrep() {
   sed -n "/$1/s/\x1/\x1b[32m|\x1b[0m/gp"
}
share|improve this answer
1  
+1 Hey punk that's a nicer version of what I said ;) –  goldilocks Sep 6 '13 at 16:38
    
You are too fast :) –  Alex Sep 6 '13 at 16:42
2  
I would go with a more portable version of: tail -f file.log | sed -n '/TEST/ "s/\x1/$(tput setaf 2)|$(tput sgr0)/gp", which will get the appropriate code for your term type for "green" and "reset" –  Drav Sloan Sep 6 '13 at 16:54
    
Thanks all! Great answers and explanations. –  Mei Sep 6 '13 at 17:13

I don't see how your command can work since (at least on my system) tail -f cannot be piped twice since the second program you pipe to (grep in your case) waits until the input has finished before printing results.

Anyway, the standard method is what goldilocks suggested, using ANSI escape color sequences. Since I do this very often, I have written a little script that will color whatever string you give it:

#!/usr/bin/env perl
use Getopt::Std;
use strict;
use Term::ANSIColor; 

my %opts;
getopts('hic:l:',\%opts);
    if ($opts{h}){
      print<<EoF; 
Use -l to specify the pattern(s) to highlight. To specify more than one 
pattern use commas. 

-l : A Perl regular expression to be colored. Multiple expressions can be
     passed as comma separated values: -l foo,bar,baz
-i : makes the search case sensitive
-c : comma separated list of colors;

EoF
      exit(0);
    }

my $case_sensitive=$opts{i}||undef;
my @color=('bold red','bold blue', 'bold yellow', 'bold green', 
           'bold magenta', 'bold cyan', 'yellow on_magenta', 
           'bright_white on_red', 'bright_yellow on_red', 'white on_black');
if ($opts{c}) {
   @color=split(/,/,$opts{c});
}
my @patterns;
if($opts{l}){
     @patterns=split(/,/,$opts{l});
}
else{
    $patterns[0]='\*';
}

# Setting $| to non-zero forces a flush right away and after 
# every write or print on the currently selected output channel. 
$|=1;

while (my $line=<>) 
{ 
    for (my $c=0; $c<=$#patterns; $c++){
    if($case_sensitive){
        if($line=~/$patterns[$c]/){
           $line=~s/($patterns[$c])/color("$color[$c]").$1.color("reset")/ge;
        }
    }
    else{
        if($line=~/$patterns[$c]/i){
          $line=~s/($patterns[$c])/color("$color[$c]").$1.color("reset")/ige;
        }
      }
    }
    print STDOUT $line;
}

If you save it as color in a directory that is in your $PATH and make it executable (chmod +x /usr/bin/color), you can color lines from your error log like this:

tr '\001' '|' < file.log | color -l "\|" 

As written, the script has predefined colors for 10 different patterns, so giving it a comma separated list as I have in the example above will color each of the patterns matched in a different color.

share|improve this answer
    
Nice script, thanks. –  Mei Sep 6 '13 at 17:18

To colorize the | character, pipe to

sed -e "s/\|/$(tput setaf 2)\\0$(tput sgr0)/g"

The terminal capabilities setaf and sgr0 are mentioned in terminfo(5).

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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