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
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It only takes a minute to sign up.
Sign up to join this communityI 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".
\001
to match the question.
Jan 20, 2016 at 9:31
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 code32
is the color green for the foreground text\x1b[0m
reset the foreground colorg
for global, replace very occurrenceYou may set it in your .bashrc
as a function (not tested)
loggrep() {
sed -n "/$1/s/\x1/\x1b[32m|\x1b[0m/gp"
}
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"
Sep 6, 2013 at 16:54
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.
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)
.