30 de Septiembre de 2010
Etiquetas: bash, color, escape, gcc, make, sed.

¿Alguna vez te has perdido intentando distinguir los errores entre todo el texto de salida del compilador? El sencillo script que presento aquí añade colores para que sea más fácil de leer, usando un comando sed. De paso es un buen ejemplo para practicar un poco con el sed. Cierto, ya hay otros programas que lo hacen, como colorgcc, pero este es mucho más sencillo: la idea básica es hacer un filtro de shell que ejecute un comando sed que añada los comandos de color en los puntos apropiados. Por si alguien está despistado, sed (de Stream EDitor) es un (potente) programa que aplica comandos de edición de texto a un fichero, o en este caso a la salida de un comando.

Sin más preámbulos, aquí está el script de filtro, que he llamado ccc:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#!/bin/bash

DEF=0
BOLD=1
DIM=2
BLACK=30
RED=31
GREEN=32
BROWN=33
BLUE=34
MAGENTA=35
CYAN=36
WHITE=37
BG_BLACK=40
BG_RED=41
BG_GREEN=42
BG_BROWN=43
BG_BLUE=44
BG_MAGENTA=45
BG_CYAN=46
BG_WHITE=47

NORM=$DEF
MAKE=$DIM
ERROR=$RED
WARN=$GREEN
LIT=$BOLD
TOOL=$CYAN\;$BOLD
OUT=$MAGENTA\;$BOLD

ESC=`printf "\033["`
E_NORM=${ESC}${NORM}m
E_MAKE=${ESC}${MAKE}m
E_ERROR=${ESC}${ERROR}m
E_WARN=${ESC}${WARN}m
E_LIT=${ESC}${LIT}m
E_TOOL=${ESC}${TOOL}m
E_OUT=${ESC}${OUT}m

sed --unbuffered \
-e "s/‘\|’/'/g" \
-e "/^\(make\|Making\)/{ s/.*/${E_MAKE}&${E_NORM}/ ; b }" \
-e "s/\<error:/${E_ERROR}&${E_NORM}/" \
-e "s/\<warning:/${E_WARN}&${E_NORM}/" \
-e "s/'[^']*'/${E_LIT}&${E_NORM}/g" \
-e "/\(gcc\|g++\|ld\) /{" \
-e "s/[^\t ]*\(gcc\|g++\|ld\) /${E_TOOL}&${E_NORM}/" \
-e "s/-o[\t ]\+[^\t ]*/${E_OUT}&${E_NORM}/" \
-e "}"

Admito que puede ser un poquito difícil de entender, así que voy a intentar explicarlo:

  • La línea 1 es el shebang, que indica qué intérprete hay que usar para ejecutarlo. No olvides que tienes que añadirle permisos de ejecución (chmod a+x ccc).
  • Las líneas 3 a 21 definen nombres para las constantes de colores, según el estándar ECMA-48. Para aplicar un atributo basta con escribir en la salida estándar el carácter de escape seguido de [, el código del atributo y m. También se pueden aplicar varios atributos a la vez separándolos con ;.
  • Las líneas 23 a 29 son la asignación de los atributos a las distintas partes de la salida del compilador. Si no te gusta mi combinación de colores puedes cambiarla aquí:

    • NORM: el texto normal.
    • MAKE: salida generada por make.
    • ERROR: errores de compilación (solo se colorea la palabra error).
    • WARN: advertencias del compilador (solo se colorea la palabra warning).
    • LIT: textos entre comillas, normalmente nombres de identificadores o trocitos de código.
    • TOOL: el nombre del compilador o del linker.
    • OUT: el nombre del fichero de salida que se está generando.
  • La línea 31 construye la cadena de caracteres ESC[. El carácter ESC es el ASCII 27 (033 en octal).

  • Las líneas 32 a 38 construyen las secuencias de escape correspondientes a los atributos de antes.
  • Las líneas 40 a 49 componen un único comando sed que filtra la entrada estándar y la escribe el resultado en la salida estándar. Nótese la opción --unbuffered para reducir al mínimo el uso de buffers y ver los mensajes en cuanto ocurran.

Como el script de sed está escrito en línea puede ser complicado de leer, así que lo transcribo a continuación en claro:

1
2
3
4
5
6
7
8
9
10
11
12
s/‘\|’/'/g
/^\(make\|Making\)/{
    s/.*/${E_MAKE}&${E_NORM}/
    b
}
s/\<error:/${E_ERROR}&${E_NORM}/
s/\<warning:/${E_WARN}&${E_NORM}/
s/'[^']*'/${E_LIT}&${E_NORM}/g
/\(gcc\|g++\|ld\) /{
    s/[^\t ]*\(gcc\|g++\|ld\) /${E_TOOL}&${E_NORM}/
    s/-o[\t ]\+[^\t ]*/${E_OUT}&${E_NORM}/
}

Está claro, ¿no?. Recuerda que sed procesa las líneas de entrada de una en una, y para cada una de ellas va aplicando los comandos del script sucesivamente.

  • La línea 1 es un comando de sustitución (s) que cambia las comillas tipográficas ‘’(las herramientas de GNU las usan de vez en cuando) por apóstrofos, que hacen las veces de comillas simples. Esto se hace antes para simplificar los comandos posteriores.
  • La línea 2 reconoce los comentarios escritos por make porque comienzan con make o Making. Si la línea es de make se ejecutan los comandos de las líneas 3 y 4 (por eso las llaves).
  • En la línea 3 se aplican los atributos MAKE a toda la línea. El & representa a la línea entera.
  • La línea 4 (branch) termina el procesado de la línea de entrada actual, de manera que la salida de make no recibe más colores.
  • La línea 5 identifica los errores del compilador por la cadena de texto error:, y lo colorea correspondientemente.
  • La línea 6 es como la 5 pero para los warnings.
  • La línea 7 reconoce los textos entre comillas y les aplica el color configurado.
  • La línea 8 encuentra las líneas que hacen referencia a los compiladores gcc, g++ o al linker ld y les aplica los dos siguientes comandos.
  • La línea 9 cambia el color del compilador o linker.
  • La línea 10 busca la opción -o y colorea la palabra siguiente, que seguramente sea el nombre del fichero generado.

Cómo se usa

Para filtrar la salida del compilador debes tener en cuenta que GCC escribe los errores en la salida de errores. Así que un pipe simple no sirve, porque solo filtraría la salida estándar, no la de errores. Hay que reenviar la salida de errores a la estándar:

$ gcc -o test test.c 2>&1 | ccc

O si usas bash puedes abreviar a:

$ gcc -o test test.c |& ccc

Claro que algunas versiones del compilador traducen los mensajes (warning pasa a ser advertencia, etc.), así que para ir sobre seguro:

$ LANG=C gcc -o test test.c |& ccc

Naturalmente, también se puede filtrar la ejecución de make:

$ LANG=C make  |& ccc

Para que sea más cómodo, he escrito el siguiente script, que llamo mmake:

#!/bin/bash
LANG=C make "$@" 2>&1 | ccc

Y ¡listo!

NOTA: en el caso de makes interactivos, como el make config del kernel de Linux, no debes usar este script, ya que el filtro interferiría con la entrada de usuario.

3 comentarios a Colorear la salida del compilador con sed

  1. Buena info sobre el sed, y los colores en terminal

    El blog tiene muy buenos contenidos, sigue escribiendo icon_smile

    zipizap

  2. Veo que ya vas cogiendo mi ritmo icon_razz

  3. Sí, bueno, estoy acumulando temas, y cuando me ponga no paro...

Ayuda
:-(icon_sad :-)icon_smile :roll:icon_rolleyes
:-Dicon_biggrin :-Picon_razz :oops:icon_redface
:-xicon_mad :-|icon_neutral :arrow:icon_arrow
8-)icon_cool 8-Oicon_eek :mrgreen:icon_mrgreen
:!:icon_exclaim :?:icon_question :twisted:icon_twisted
;-)icon_wink :evil:icon_evil :idea:icon_idea
:-oicon_surprised :cry:icon_cry
:-?icon_confused :lol:icon_lol

Deja un comentario