una - grep a través de texto de color, por ejemplo, gcc | colorgcc | gregaria regexp



expresiones regulares unix (1)

¿Cómo puedo hacer que grep respete los escapes de color ANSI cuando se reemplaza la salida canalizada? Me complace usar algo más (perl?) En lugar de grep.

Mi usercase: quiero

 gcc foobar.c | colorgcc | grep regexp
 ls --color | grep filename

funciona bien con colores (en un terminal Unix que usa escapes ANSI).

Los ejemplos de prueba de comportamiento que quiero:

echo -e "he\e[35mllo\e[00m" world |grep hell ==> he\e[35mllo\e[00m world 
echo -e "\e[35m removed line\nhello\e[00m" world |grep hell ==> \e[35mhello\e[00m world
echo -e "\e[35m rem\e[1moved line\nhello\e[00m" world | grep hell ==> \e35m\e1mhello\e[00m world

Actualmente, la primera línea da la cadena vacía, y la segunda da una cadena sin color 'hello \ e [00m world'. Aquí \ e [35m y \ e00m son modificadores de color (atributo): el color de una letra está determinado por las últimas secuencias de escape de color (atributo) de form \ e [P1; P2; .. m donde P1, P2, etc. son secuencias de dígitos; \ e [P1m \ e [P2m es equivalente a \ e [P1; P2m. \ e [0m hace que el color sea el predeterminado y olvida todas las secuencias \ e [.. m anteriores: \ e [34m \ e [0m equivale a \ e [0m. Hay varios atributos independientes (audacia, color del fondo, color de primer plano / letra); cada número en una secuencia de escape afecta solo a uno de ellos. Así \ e [1m \ e [35m es equivalente a \ e [1; 35m pero no \ e [35; 1m ni \ e [35m; sin embargo, \ e [34m \ e [35m son equivalentes a \ e [35m porque ambos afectan al mismo attirbute (es decir, el color de la letra / foregrnound).


Este es un problema realmente interesante, aquí es lo que se me ocurrió. Es bastante feo pero parece hacer el trabajo:

sed -n '1s/^/\x1b[0m/;H;x;s/\n//;p;s/.*\(\x1b\[[0-9]*m\(;[0-9]*m\)*\).*/\1/;h' |
  grep `sed 's/./\0\\\\(\x1b\\\\[[0-9]*m\\\\(;[0-9]*m\\\\)*\\\\)*/g' <<< hell`

El término que está buscando se colocaría al final (en lugar de "infierno"), aquí hay algunos ejemplos con el texto que proporcionó (usando hexdump para mostrar los colores):

$ echo -e "he\e[35mllo\e[00m" world |
> sed -n '1s/^/\x1b[0m/;H;x;s/\n//;p;s/.*\(\x1b\[[0-9]*m\(;[0-9]*m\)*\).*/\1/;h' |
> grep `sed 's/./\0\\\\(\x1b\\\\[[0-9]*m\\\\(;[0-9]*m\\\\)*\\\\)*/g' <<< hell` |
> hexdump -C
00000000  1b 5b 30 6d 68 65 1b 5b  33 35 6d 6c 6c 6f 1b 5b  |.[0mhe.[35mllo.[|
00000010  30 30 6d 20 77 6f 72 6c  64 0a                    |00m world.|
0000001a

$ echo -e "\e[35m removed line\nhello\e[00m" world |
> sed -n '1s/^/\x1b[0m/;H;x;s/\n//;p;s/.*\(\x1b\[[0-9]*m\(;[0-9]*m\)*\).*/\1/;h' |
> grep `sed 's/./\0\\\\(\x1b\\\\[[0-9]*m\\\\(;[0-9]*m\\\\)*\\\\)*/g' <<< hell` |
> hexdump -C
00000000  1b 5b 33 35 6d 68 65 6c  6c 6f 1b 5b 30 30 6d 20  |.[35mhello.[00m |
00000010  77 6f 72 6c 64 0a                                 |world.|
00000016

El primer comando sed precede la configuración de color actual al comienzo de cada línea, lo cual es necesario para su segundo ejemplo, donde el color se establece en una línea que grep omitirá. El comando sed que es el argumento para grep inserta una expresión regular que coincidirá con cualquier cantidad de escapes de color entre cada carácter en el término de búsqueda.

Aquí está la versión de egrep:

sed -n '1s/^/\x1b[0m/;H;x;s/\n//;p;s/.*\(\x1b\[[0-9]*m\(;[0-9]*m\)*\).*/\1/;h' |
  egrep `sed 's/./\0(\x1b\\\\[[0-9]*m(;[0-9]*m)*)*/g' <<< hell`




grep