grep com saída colorida retorna várias linhas vazias

3

Eu tenho um problema estranho com o grep (2.12-2, teste debian).

Em algumas situações, quando faço algo assim: grep -rni '."spacer">.' . grep me retorna várias linhas vazias:

Se eu adicionar --color=none , todas as linhas se tornarão visíveis.

opções do grep em .bashrc:

export GREP_COLORS='fn=01;34:ms=01;33:ln=33'
alias grep='grep --color=auto'
    
por loadaverage 12.04.2013 / 18:50

1 resposta

6

Uma ferramenta muito útil para depurar esse tipo de coisa é od . Passar a saída do comando grep através de od mostrou que seu arquivo contém terminações de linha no estilo DOS, retorno de carro ( \r ) seguido por uma nova linha ( \n ):

$ grep -i '."spacer">.' default.php | od -c
0000000  \t  \t  \t  \t  \t   <   d   i   v       c   l   a   s   s   =
0000020   "   s   p   a   c   e   r   "   >  \r  \n  \t  \t  \t   <   d
0000040   i   v       c   l   a   s   s   =   "   s   p   a   c   e   r
0000060   "   >  \r  \n
0000064

Então, para testar, criei este arquivo de teste mínimo:

$ echo -ne "<div class=\"spacer\">\r\n<div class=\"spacer\">\r\n" > foo.php
$ cat foo.php 
<div class="spacer">
<div class="spacer">

Confirmei que grep imprime linhas vazias:

$ grep -i '."spacer">.' foo.php 


$

A razão que está imprimindo linhas vazias é o retorno de carro ( \r ). Você está pedindo para o grep encontrar a string spacer"> e o caractere seguinte . Em seu arquivo, o caractere a seguir é \r . Imprimir \r no terminal tem o efeito de limpar a última linha impressa, resultando na exibição de uma linha vazia. Você pode testar isso com o seguinte comando:

$ echo -e "foo\rbar"
bar

O que realmente acontece é que o primeiro foo é impresso, depois excluído por causa de \r e substituído por bar . Verifique com od :

$ echo -e "foo\rbar" | od -c
0000000   f   o   o  \r   b   a   r  \n
0000010

Agora, não entendo por que a opção colors de grep está mudando as coisas. Deve ter algo a ver com a forma como os caracteres especiais são exibidos. Em qualquer caso, você pode corrigir seu problema removendo todos os \r :

$ sed 's/\r//g' default.php > bar.php

Em seguida, remova o último . do seu padrão grep (lembre-se que por padrão . não corresponde a novas linhas, embora corresponda a \r ):

$ grep -ni '."spacer">' bar.php 
103:                <div class="spacer">
222:            <div class="spacer">
    
por 13.04.2013 / 18:36