Por que clang gera texto ininteligível quando redirecionado?

20

Estou tentando salvar a saída de um comando em um arquivo. O comando é:

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

No entanto, o arquivo output.txt resultante quando aberto (pelo gedit e jedit no ubuntu) me fornece o seguinte:

[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
...

Quando realmente deve ficar assim:

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'
...

Eu pensei que poderia ser um problema de codificação, verifiquei a codificação do arquivo, file -bi output.txtque sai text/plain; charset=us-ascii.

Eu pensei que talvez se eu mudar a codificação para utf-8 o problema seria corrigido, então eu tentei isso:

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

mas não fez diferença.

O que posso fazer para resolver este problema?

O problema não é que estou tentando visualizar a versão destacada pela sintaxe (não tive problemas para visualizá-la). Preciso salvar o AST gerado pelo clang em um arquivo e analisá-lo, o que seria difícil com as informações de cores deixadas no.

maou
fonte
4
Vale ressaltar que >não gera saída, simplesmente designa para o shell que você deseja colocar a saída do seu clangcomando no arquivo fornecido, em vez do terminal. Depois disso, você a visualiza de uma maneira que não permite códigos de cores da mesma maneira. Se você estivesse catno arquivo, ele funcionaria como o terminal assumiria, e você pode lessfazer o mesmo com a -Rbandeira.
Sammitch 30/04
@ Scott - Não estou tentando visualizar a saída, estou tentando salvá-la no arquivo sem deixar as informações de cores, o que tornaria a análise do arquivo desnecessariamente complicada.
maou

Respostas:

54

Não tem nada a ver com páginas de código / codificação. Sua saída não é texto simples. Ele contém as seqüências como [0;1;32m. Essas cadeias (existe um caractere [escape], não mostrado, bem antes de cada uma delas) são instruções para o terminal exibir texto em negrito, itálico, em várias cores, etc. Isso resulta em uma saída de leitura mais fácil, se o seu terminal suporta isso.

Deve haver uma opção para dizer ao clang para não tentar embelezar a saída, mas use texto sem formatação. Verifique o manual. (Eu não tenho um útil, por isso não posso lhe dizer qual seria o comando adequado.)

Tonny
fonte
15
Obrigado, essa foi a causa. Eu tentei o clang -Xclang -ast-dump -fsyntax-only -fno-color-diagnostics main.cpp > output.txtque me deu a saída correta.
maou
9
Uma correção alternativa, se o Clang for razoavelmente bem-comportado (o que obviamente não é, se estiver enviando códigos de terminal sem verificação isatty(stdout)) é definido TERMcomo (por exemplo) dumb.
Toby Speight
4
Re "Isso resulta em uma leitura mais fácil, se o seu terminal suportar.", Isto é, obviamente, uma opinião. Nem sempre funciona dessa maneira, como por exemplo, quando o aplicativo de coloração gera texto azul escuro em seu fundo preto :-(
jamesqf 28/04
4
Qualquer software razoável deve detectar que sua saída está sendo redirecionada para o arquivo e, nesse caso, desativar a colorização.
n0rd
11
@ n0rd Idealmente, sim, mas já vi situações suficientes em que isattty () não era falso na saída redirecionada. E, em alguns casos, um usuário pode querer que os códigos de escape sejam redirecionados (por exemplo, para exibir mais tarde ou canalizar para o netcat para exibir em outro sistema, apenas para fornecer 2 casos de uso). Portanto, tente adivinhar, mas também permita que o usuário o ligue / desligue, substituindo a suposição, caso esteja errado. Essa seria a melhor solução.
Tonny
12

Como alternativa, em vez de remover as cores da saída, você pode visualizar a saída colorida no seu terminal usando a opção bruta de less

less -r output.txt
987poiuytrewq
fonte
2

Esses caracteres, como o [0;33mcontrole de saída do terminal , parecem para mim. Eles fazem parte de um conjunto de seqüências de escape frequentemente usadas para aplicar cores ao texto no terminal. Em seu estado bruto como esse, também é frequentemente usado para aplicar cores ao próprio prompt do bash - Aqui está o que eu venho usando .bashrchá anos em todas as minhas 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\]'

(A maioria acha que é feio, mas eu gosto).

Veja se você consegue encontrar uma opção para remover qualquer código de cores ou similar da saída de seus comandos e veja se isso ajuda.

Jarmund
fonte
13
[...] "parecem o controle de saída do bash para mim" Eles não têm nada a ver com o bash. É para o terminal que servem.
glglgl
11
Como o @glglgl disse, eles não são específicos do Bash, são xtermalgo relacionado. Veja esta excelente resposta do desenvolvedor principal do xterm.
gato
@glglgl Tudo bem, resposta editada em conformidade. Eu o vi pela primeira vez ao migrar do fBSD para o linux alguns anos atrás, que também foi quando comecei a usar o bash, então achei que era um produto desse último.
Jarmund 29/04