grep --color = quebra automática quando ^ M está dentro do jogo colorido

4

Eu tenho 2 arquivos similares (dos.txt e unix.txt) com o texto The quick brown fox jumps\n over the lazy dog. que diferem pelos finais de linha. Quando procuro uma palavra no final da linha, a saída do dos.txt está vazia:

$ grep -E 'jumps^M?$' dos.txt unix.txt

unix.txt:The quick brown fox jumps

O Grep encontra algo, mas não o imprime. A saída real do grep é assim:

$ grep -E --color=always 'jumps^M?$' dos.txt unix.txt | cat -v
^[[35m^[[Kdos.txt^[[m^[[K^[[36m^[[K:^[[m^[[KThe ... ^[[01;31m^[[Kjumps^M^[[m^[[K
^[[35m^[[Kunix.txt^[[m^[[K^[[36m^[[K:^[[m^[[KThe ... ^[[01;31m^[[Kjumps^[[m^[[K

Portanto, parece que a única diferença é que ^ M está dentro da saída colorida e faz com que toda a linha desapareça. Como posso consertar isso (sem converter dos arquivos usando dos2unix ou ferramentas similares)?

    
por mx0 09.03.2017 / 20:19

2 respostas

6

Após algumas pesquisas para a sequência de escape ^[[K , leia metade de um livro sobre o terminal VT100 e verificando man grep Descobri que a variável de ambiente de configuração GREP_COLORS to

GREP_COLORS=ne

Fornece a saída desejada:

$ export GREP_COLORS=ne
$ grep -E --color=always 'jumps^M?$' dos.txt unix.txt
dos.txt:The quick brown fox jumps
unix.txt:The quick brown fox jumps

$ grep -E --color=always 'jumps^M?$' dos.txt unix.txt | cat -v
^[[35mdos.txt^[[m^[[36m:^[[mThe ... ^[[01;31mjumps^M^[[m
^[[35munix.txt^[[m^[[36m:^[[mThe ... ^[[01;31mjumps^[[m

Da página de manual grep :

ne     Boolean  value  that prevents clearing to the
       end of line using Erase in Line (EL) to Right
       ([K)  each  time  a  colorized  item ends.
       This is needed on terminals on  which  EL  is
       not  supported.   It  is  otherwise useful on
       terminals  for  which  the   back_color_erase
       (bce)  boolean  terminfo  capability does not
       apply, when the chosen  highlight  colors  do
       not  affect the background, or when EL is too
       slow or causes too much flicker.  The default
       is false (i.e., the capability is omitted).

No meu caso, funciona bem mesmo se eu definir a cor de destaque para algo que mude de fundo:

export GREP_COLORS="ne:mt=41;38"

Agora, a questão interessante é por que ^[[K produz essa linha em branco.

Caractere ^M significa retorno de carro sem passar para a próxima linha:

$ echo -e "start^Mend"
endrt

^[[K limpa a linha do cursor para a direita e depois escreve o resto da linha:

$ echo -e "start3[Kend"
startend

No entanto, quando você coloca ^M antes de ^[[K , ele remove o conteúdo:

$ echo -e "start^M3[Kend"
end

Depois de escrever o start , o cursor vai para o início da linha e, em seguida, ^[[K remove tudo e o restante da linha é gravado. No caso de grep output, a primeira linha escreve tudo até o word jumps , depois volta para o início da linha ^M , escreve inofensivo ^[[m sequence e ^J que vai para a nova linha. É por isso que ^[[K após ^M limpa toda a linha.

    
por 09.03.2017 / 22:25
1

Você pode canalizar a saída através de tr (1) e descartar as retornos de carro. tr -d '\r' eliminará todos os retornos de carro.

Isso funciona:

grep --color=always -E 'jumps' dos.txt unix.txt | tr -d '\r'

(também funciona com o ^M? .)

Dica: Saída de tubulação para menos (1) sempre que você suspeitar que a saída pode conter caracteres inseguros.

    
por 09.03.2017 / 20:35

Tags