2

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
4

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/\001/\\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".

  • What does the 'a' stand for in sed s/a/... ? – netigger Jan 20 '16 at 9:20
  • @DavidEverlöf Good question...I'm guessing I meant to explain that as whatever character (as in "replace a with b") ??? But the OP got it so I never noticed. Anyway, I've replaced that with \001 to match the question. – goldilocks Jan 20 '16 at 9:31
  • No wonder I didnt find anything about anywhere =) Alright, thx. – netigger Jan 21 '16 at 7:57
4
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"
}
  • 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
2

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.

1

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).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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