Dlaczego po przekierowaniu klang generuje niezrozumiały tekst?

20

Próbuję zapisać dane wyjściowe polecenia w pliku. Polecenie to:

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

Jednak wynikowy plik output.txt po otwarciu (przez gedit i jedit na ubuntu) daje mi to:

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

Kiedy naprawdę powinno to wyglądać tak:

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

Myślałem, że może to być problem z kodowaniem, sprawdziłem kodowanie pliku, file -bi output.txtktóry wyprowadza text/plain; charset=us-ascii.

Pomyślałem, że jeśli zmienię kodowanie na utf-8, problem zostanie rozwiązany, więc spróbowałem:

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

ale to nie miało znaczenia.

Co mogę zrobić, aby rozwiązać ten problem?

Problemem nie jest to, że próbuję wyświetlić wersję z podświetloną składnią (nie miałem problemu z jej obejrzeniem). Muszę zapisać plik AST wygenerowany przez clang do pliku, a następnie parsować go, co byłoby trudne przy pozostawionych informacjach o kolorze.

maou
źródło
4
Warto zauważyć, że >nie generuje danych wyjściowych, po prostu oznacza w powłoce, że chcesz umieścić dane wyjściowe clangpolecenia w danym pliku, a nie w terminalu. Następnie oglądasz go w sposób, który nie dopuszcza kodów kolorów w ten sam sposób. Jeśli przejdziesz do catpliku, działałoby to tak, jakby przejął go terminal i możesz lesszrobić to samo z -Rflagą.
Sammitch,
@Scott - Nie próbuję wyświetlić wyniku, próbuję zapisać go do pliku bez pozostawiania informacji o kolorze, co spowodowałoby, że parsowanie pliku byłoby niepotrzebnie skomplikowane.
maou

Odpowiedzi:

54

Nie ma to nic wspólnego ze stronami kodowymi / kodowaniem. Twój wynik nie jest zwykłym tekstem. Zawiera takie sekwencje jak [0;1;32m. Te ciągi (przed każdym z nich znajduje się również nie pokazany znak [ucieczki]) są instrukcjami dla terminala, aby wyświetlać pogrubiony tekst, kursywę, w różnych kolorach itp. W rezultacie terminal jest łatwiejszy do odczytania, jeśli twój terminal obsługuje to.

Powinna istnieć opcja informowania clang, aby nie próbował upiększać wyników, ale zamiast tego użyj zwykłego tekstu. Sprawdź instrukcję. (Nie mam jednej poręczności, więc nie mogę powiedzieć, jakie byłoby właściwe polecenie).

Tonny
źródło
15
Dzięki, to była przyczyna. Próbowałem, clang -Xclang -ast-dump -fsyntax-only -fno-color-diagnostics main.cpp > output.txtco dało mi prawidłowy wynik.
maou
9
Alternatywną poprawką, jeśli Clang jest dość grzeczny (co oczywiście nie jest, jeśli wysyła kody terminali bez sprawdzania isatty(stdout)), należy ustawić TERMna (np dumb. ) .
Toby Speight
4
Re „Powoduje to łatwiejszy do odczytania wynik, jeśli twój terminal go obsługuje.”, To jest oczywiście opinia. Nie zawsze tak działa, na przykład gdy aplikacja do kolorowania wyświetla ciemnoniebieski tekst na czarnym tle :-(
jamesqf 28.04.2016
4
Każdy rozsądny program powinien wykryć, że jego dane wyjściowe są przekierowywane do pliku i w takim przypadku wyłączyć kolorowanie.
n0rd
1
@ n0rd Idealnie tak, ale widziałem wystarczającą liczbę sytuacji, w których isattty () nie otrzymał wartości false przy przekierowanym wyjściu. W niektórych przypadkach użytkownik może chcieć przekierować kody specjalne (np. Aby wyświetlić później lub potokować do netcat, aby wyświetlić w innym systemie, aby podać 2 przypadki użycia). Spróbuj zgadnąć, ale pozwól również użytkownikowi włączyć / wyłączyć, zastępując zgadywanie na wypadek, gdyby było to błędne. To byłoby najlepsze rozwiązanie.
Tonny
12

Alternatywnie, zamiast usuwania kolorów z danych wyjściowych, możesz wyświetlić kolorowe dane wyjściowe w terminalu, używając opcji raw less

less -r output.txt
987poiuytrewq
źródło
2

Te znaki, takie jak [0;33mdla mnie, wyglądają jak sterowanie wyjściami terminala. Są częścią zestawu sekwencji specjalnych, które są często używane do nakładania kolorów na tekst w terminalu. W stanie surowym, takim jak ten, jest również często używany do nakładania koloru na sam monit bash - oto, czego używałem .bashrcod lat na wszystkich moich maszynach:

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

(Większość uważa, że ​​to brzydkie, ale mi się podoba).

Sprawdź, czy jesteś w stanie znaleźć przełącznik, aby usunąć kodowanie kolorami itp. Z wyników poleceń i sprawdź, czy to pomoże.

Jarmund
źródło
13
[...] „wygląda mi na kontrolę wyjścia bash” Nie mają one nic wspólnego z bash. Do tego służą.
glglgl 28.04.16
1
Jak powiedział @glglgl, nie są one specyficzne dla Bash, są związane z tym xterm. Zobacz tę doskonałą odpowiedź wiodącego autora xterm.
kot
@glglgl W porządku, odpowiedź odpowiednio zmodyfikowana. Po raz pierwszy zobaczyłem to podczas migracji z fBSD do Linuksa kilka lat temu, kiedy to zacząłem używać bash, więc pomyślałem, że to wynik tego ostatniego.
Jarmund