Como mudar a cor de um caractere enquanto segue e tr

2

Eu uso regularmente esta linha de comando, mas eu gostaria de mudar a cor do "|" para verde na saída. Alguém sabe como posso conseguir isso?

tail -f file.log  | tr '
tail -f file.log  | tr '%pre%1' '|' | grep TEST
1' '|' | grep TEST
    
por Mei 06.09.2013 / 17:51

4 respostas

4

Eu não acho que você pode com tr porque o conjunto de substituição é truncado para a duração do conjunto de correspondência, e a mudança de cor requer alguns caracteres de controle.

Não impossível com sed tho:

tail -f file.log  | sed s/
echo -e "3[32m|3[0m"
1/\x1b[32m\|\x1b[0m/g

1b é hexadecimal para octal 33 , visto em coisas como prompts de cor porque o shell gosta de octal (mas para obter caracteres de controle "não imprimíveis" através de sed , use hexadecimal). Por exemplo, para imprimir apenas uma barra verde:

tail -f file.log  | sed s/
echo -e "3[32m|3[0m"
1/\x1b[32m\|\x1b[0m/g

As seqüências de controle são "seqüências de escape ANSI", veja aqui para detalhes (32 é primeiro plano verde, 0 é redefinido). Octal 33 = decimal 27 = o caractere ASCII 'ESC', portanto, "seqüência de escape".

    
por 06.09.2013 / 18:33
4
tail -f file.log  | sed -n '/TEST/s/\x1/\x1b[32m|\x1b[0m/gp'
  • -n tell sed para suprimir a saída por padrão (mas o% finalp dirá para imprimir as linhas correspondentes, uma espécie de grep)
  • /TEST/ seleciona apenas as linhas que correspondem (como grep)
  • s para substituir \x1 ( \x é o escape do shell para valores hexadecimais) com \x1b[32m|\x1b[0m .
    • \x1b[ inicia um código de escape ANSI
    • 32 é a cor verde para o texto em primeiro plano
    • \x1b[0m redefiniu a cor do primeiro plano
    • g para global, substitui muito a ocorrência

Você pode configurá-lo no seu .bashrc como uma função ( não testada )

loggrep() {
   sed -n "/$1/s/\x1/\x1b[32m|\x1b[0m/gp"
}
    
por 06.09.2013 / 18:36
2

Eu não vejo como seu comando pode funcionar desde (pelo menos no meu sistema) tail -f não pode ser canalizado duas vezes desde que o segundo programa que você canaliza ( grep no seu caso) aguarda até que a entrada termine antes resultados de impressão.

De qualquer forma, o método padrão é o que os goldilocks sugeriram, usando sequências de cores de escape ANSI . Como faço isso com muita frequência, escrevi um pequeno script que colore qualquer string que você der:

#!/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;
}

Se você salvá-lo como color em um diretório que esteja em $PATH e torná-lo executável (chmod + x / usr / bin / color), poderá colorir linhas de seu log de erros da seguinte forma:

tr '
#!/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;
}
1' '|' < file.log | color -l "\|"

Conforme escrito, o script tem cores predefinidas para 10 padrões diferentes, portanto, dar a ele uma lista separada por vírgulas como no exemplo acima irá colorir cada um dos padrões correspondidos em uma cor diferente.

    
por 06.09.2013 / 18:43
1

Para colorir o caractere | , canalizar para

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

Os recursos do terminal setaf e sgr0 são mencionados em terminfo(5) .

    
por 06.09.2013 / 20:28