¿Por qué Clang genera texto ininteligible cuando se redirige?

20

Estoy tratando de guardar la salida de un comando en un archivo. El comando es:

clang -Xclang -ast-dump -fsyntax-only main.cpp > output.txt

Sin embargo, el archivo resultante output.txt cuando se abre (por gedit y jedit en ubuntu) me da esto:

[0;1;32mTranslationUnitDecl[0m[0;33m 0x4192020[0m <[0;33m<invalid sloc>[0m> [0;33m<invalid sloc>[0m
[0;34m|-[0m[0;1;32mTypedefDecl[0m[0;33m 0x4192558[0m <[0;33m<invalid sloc>[0m> [0;33m<invalid sloc>[0m implicit[0;1;36m __int128_t[0m [0;32m'__int128'[0m
[0;34m| `-[0m[0;32mBuiltinType[0m[0;33m 0x4192270[0m [0;32m'__int128'[0m
[0;34m|-[0m[0;1;32mTypedefDecl[0m[0;33m 0x41925b8[0m <[0;33m<invalid sloc>[0m> [0;33m<invalid sloc>[0m implicit[0;1;36m __uint128_t[0m [0;32m'unsigned __int128'[0m
[0;34m| `-[0m[0;32mBuiltinType[0m[0;33m 0x4192290[0m [0;32m'unsigned __int128'[0m
...

Cuando realmente debería verse así:

TranslationUnitDecl 0x4e46020 <<invalid sloc>> <invalid sloc>
|-TypedefDecl 0x4e46558 <<invalid sloc>> <invalid sloc> implicit __int128_t '__int128'
| `-BuiltinType 0x4e46270 '__int128'
|-TypedefDecl 0x4e465b8 <<invalid sloc>> <invalid sloc> implicit __uint128_t 'unsigned __int128'
| `-BuiltinType 0x4e46290 'unsigned __int128'
...

Pensé que podría ser un problema de codificación, verifiqué la codificación del archivo, file -bi output.txtque sale text/plain; charset=us-ascii.

Pensé que si cambiaba la codificación a utf-8, el problema se solucionaría, así que intenté esto:

clang -Xclang -ast-dump -fsyntax-only main.cpp | iconv -f us-ascii -t UTF-8 > output.txt

Pero no hizo la diferencia.

¿Qué puedo hacer para resolver este problema?

El problema no es que estoy tratando de ver la versión resaltada de sintaxis (no tuve problemas para verla en primer lugar). Necesito guardar el AST generado por clang en un archivo y luego analizarlo, lo que sería difícil con la información de color que queda.

maou
fuente
44
Vale la pena señalar que >no genera salida, simplemente designa al shell que desea colocar la salida de su clangcomando en el archivo dado, en lugar de la terminal. Después de eso, lo está viendo de una manera que no permite códigos de color de la misma manera. Si estuviera en catel archivo, funcionaría ya que la terminal se haría cargo, y puede hacer lesslo mismo con la -Rbandera.
Sammitch
@Scott: no estoy tratando de ver el resultado, estoy tratando de guardarlo en un archivo sin dejar la información de color, lo que haría que analizar el archivo sea innecesariamente complicado.
maou

Respuestas:

54

No tiene nada que ver con las páginas de códigos / codificación. Su salida no es texto sin formato. Contiene las secuencias como [0;1;32m. Estas cadenas (hay un carácter [escape], no mostrado, antes de cada una de estas) son instrucciones para que el terminal muestre texto en negrita, cursiva, en varios colores, etc. Esto da como resultado una salida más fácil de leer, si su terminal lo apoya

Debería haber una opción para decirle a clang que no intente embellecer la salida, sino que utilice texto sin formato. Consulta el manual. (No tengo uno a mano, así que no puedo decirte cuál sería el comando adecuado).

Tonny
fuente
15
Gracias, esa fue la causa. Intenté lo clang -Xclang -ast-dump -fsyntax-only -fno-color-diagnostics main.cpp > output.txtque me dio la salida correcta.
maou
99
Una solución alternativa, si Clang se comporta razonablemente bien (lo que obviamente no es así, si está enviando códigos de terminal sin verificar isatty(stdout)) es establecer TERMen (por ejemplo) dumb.
Toby Speight
44
Re "Esto resulta en una salida más fácil de leer, si su terminal lo admite", eso es, por supuesto, una opinión. No siempre funciona de esa manera, como por ejemplo cuando la aplicación de color emite texto azul oscuro sobre su fondo negro :-(
jamesqf
44
Cualquier pieza de software razonable debería detectar que su salida se está redirigiendo a un archivo y desactivar la coloración en ese caso.
n0rd
1
@ n0rd Idealmente sí, pero he visto suficientes situaciones en las que isattty () no recibió falso en la salida redirigida. Y en algunos casos, un usuario puede desear que los códigos de escape se redirijan (por ejemplo, para verlos más tarde o canalizarlos a netcat para ver en otro sistema, solo para dar 2 casos de uso). Por lo tanto, intente adivinar, pero también permita que el usuario lo active / desactive anulando la suposición en caso de que fuera incorrecto. Esa sería la mejor solución.
Tonny
12

Alternativamente, en lugar de eliminar los colores de la salida, puede ver la salida de color en su terminal utilizando la opción sin procesar de less

less -r output.txt
987poiuytrewq
fuente
2

Esos caracteres, como el [0;33mcontrol de salida de terminal para mí. Forman parte de un conjunto de secuencias de escape que se utilizan con frecuencia para aplicar colores al texto en el terminal. En su estado bruto como este, también se usa a menudo para aplicar color al indicador de bash en sí mismo: esto es lo que he estado usando .bashrcdurante años en todas mis máquinas:

export PS1='\[\033[1;33m\]\u\[\033[1;35m\]@\[\033[1;32m\]\h\[\033[0;36m\]\w\[\033[1;37m\]\$ \[\033[0;37m\]'

(La mayoría piensa que es feo, pero me gusta).

Vea si puede encontrar un interruptor para eliminar cualquier código de color o similar de la salida de sus comandos y vea si eso ayuda.

Jarmund
fuente
13
[...] "me parece el control de salida de bash" No tienen nada que ver con bash. Es la terminal para lo que son.
glglgl
1
Como dijo @glglgl, no son específicos de Bash, son algo xtermrelacionado. Vea esta excelente respuesta del desarrollador principal de xterm.
gato
@glglgl Muy bien, la respuesta editada en consecuencia. Lo vi por primera vez cuando migraba de fBSD a Linux hace unos años, que también fue cuando comencé a usar bash, así que pensé que era un producto de este último.
Jarmund