Filtra a saída do comando por cor

12

Estou executando um utilitário que não oferece uma maneira de filtrar sua saída. Nada no texto da saída indica que uma função específica falhou, mas aparece em vermelho. A saída é tão longa que, no final, quando ela reporta um número de erros, nem sempre consigo rolar para ver a saída em que ocorreu o erro.

Como posso filtrar texto não vermelho?

pseudo código:

dolongtask | grep -color red

Editar

O comando também gera outras cores e eu preciso filtrar fora todo o texto que não é vermelho. Também a coloração do texto é multilinha.

    
por ogc-nick 06.06.2014 / 02:18

2 respostas

13

Mudar a cor é feito através de seqüências de escape embutidas no texto. Invariavelmente, os programas emitem seqüências de escape ANSI , porque é isso que virtualmente todos os terminais suportam atualmente.

A seqüência de escape para mudar a cor do primeiro plano para vermelho é \e[31m , onde \e designa um caractere de escape (octal 033, hexadecimal 1b, também conhecido como ESC, ^[ e várias outras designações). Números no intervalo 30–39 definem a cor de primeiro plano; outros números definem atributos diferentes. \e[0m redefine todos os atributos para seu valor padrão. Execute cat -v para verificar o que o programa imprime, pode usar alguma variante como \e[0;31m para primeiro redefinir todos os atributos ou \e[3;31 para também alternar itálico (que muitos terminais não suportam).

Em ksh, bash ou zsh, você pode usar $'…' para ativar escapes de barra invertida dentro das aspas, o que permite digitar $'\e' para obter um caractere de escape. Note que você terá que dobrar qualquer barra invertida que você queira passar para grep . Em /bin/sh , você pode usar "$(printf \e)" ou digitar um caractere de escape literal.

Com a opção -o do GNU grep, o seguinte snipet filtra texto vermelho, assumindo que ele começa com a seqüência de escape \e[31m , termina com \e[0m ou \e[30m na mesma linha e não contém escape embutido sequência.

grep -Eo $'\e\[31m[^\e]*\e\[[03]?m'

O fragmento awk a seguir extrai texto em vermelho, mesmo quando é multilinha.

awk -v RS='3' '
    match($0, /^\[[0-9;]*m/) {
        color = ";" substr($0, 2, RLENGTH-2) ";";
        $0 = substr($0, RLENGTH+1);
        gsub(/(^|;)0*[^03;][0-9]*($|;)/, ";", color);
        red = (color ~ /1;*$/)
    }
    red'

Aqui está uma variação que retém os comandos de mudança de cor, o que pode ser útil se você estiver filtrando várias cores (aqui leia e magenta).

awk -v RS='3' '
    match($0, /^\[[0-9;]*m/) {
        color = ";" substr($0, 2, RLENGTH-2) ";";
        printf "3%s", substr($0, 1, RLENGTH);
        $0 = substr($0, RLENGTH+1);
        gsub(/(^|;)0*[^03;][0-9]*($|;)/, ";", color);
        desired = (color ~ /[15];*$/)
    }
    desired'
    
por 06.06.2014 / 03:17
6

Você pode fazer com que o grep procure por caracteres de controle, alguns dos quais são responsáveis por criar cores bonitas no terminal.

dolongtask | grep '[[:cntrl:]]'

Por exemplo, isso ecoa um "teste" vermelho no grep, que é encontrado por estar cercado por caracteres de controle:

$ echo -e '3[00;31mtest3[00m' | grep --color=none '[[:cntrl:]]'
test     <-- in red

O --color=none é apenas para garantir que o grep não aplique sua própria colorização à saída correspondente, mas imprime a linha inteira fielmente, de forma que os caracteres de controle sejam interpretados pelo shell.

    
por 06.06.2014 / 02:25