Jak wyczyścić dane wyjściowe polecenia Linux „script”

35

Korzystam z linuksowego polecenia „skrypt” http://www.linuxcommand.org/man_pages/script1.html do śledzenia niektórych interaktywnych sesji. Pliki wyjściowe z tego zawierają znaki niedrukowalne, w tym moje naciśnięcia klawiszy z backspace.

Czy istnieje sposób na uporządkowanie tych plików wyjściowych, aby zawierały tylko to, co było wyświetlane na ekranie?

A może istnieje inny sposób rejestrowania interaktywnej sesji powłoki (wejście i wyjście)?

Andrzej
źródło
„Czy istnieje inny sposób rejestrowania interaktywnej sesji powłoki (wejściowej i wyjściowej)?” Czy znasz asciinema.org ?
masterxilo

Odpowiedzi:

34

Jeśli chcesz wyświetlić plik, możesz wysłać dane wyjściowe przez col -bp; interpretuje to znaki kontrolne. Następnie możesz przepuścić mniej, jeśli chcesz.

col -bp typescript | less -R

W niektórych systemach colnie akceptuje argumentu nazwy pliku, zamiast tego użyj tej składni:

col -bp <typescript | less -R
Arcege
źródło
1
w moim systemie colnie zaakceptuje nazwy pliku, więc zrobiłem to col -bp < typescript i dostałem to, czego chciałem.
Andrew
Nie działa dla mnie, szyfruje część wyników.
Alex
1
less -RSam w moim systemie zapewnia lepszą wydajność niż przepuszczanie przez col -bppierwszy.
Brian Hawkins,
@BrianHawkins I zgadzam się. Używanie col -bp <typescript | less -Rnie wyświetla pokolorowanej konsoli. Użycie less -R typescriptwyświetla kolorową konsolę!
Trevor Boyd Smith
jest to dobre tylko wtedy, gdy chcesz przeglądać skrypt interaktywnie less.
Trevor Boyd Smith
18
cat typescript | perl -pe 's/\e([^\[\]]|\[.*?[a-zA-Z]|\].*?\a)//g' | col -b > typescript-processed

oto interpretacja ciągu znaków wejściowego do perl:

  • s/pattern//goznacza wykonanie podstawienia dla całego ( gopcja oznacza zrobienie wszystkiego zamiast zatrzymywania się na pierwszym zastępstwie)

oto interpretacja wzorca wyrażenia regularnego:

  • \e dopasuj specjalny znak kontrolny „escape” (ASCII 0x1A)
  • (i )są początkiem i końcem grupy
  • |oznacza, że ​​grupa może dopasować jeden z N wzorów. gdzie są wzorce N.
    • [^\[\]] lub
    • \[.*?[a-zA-Z] lub
    • \].*?\a
  • [^\[\]] znaczy
    • dopasuj zestaw znaków NOT, gdzie nie są znaki [i]
  • \[.*?[a-zA-Z] znaczy
    • dopasuj ciąg zaczynający się od, a [następnie zrób non-zachłanny .*?aż do pierwszego znaku alfa
  • \].*?\a znaczy
    • dopasuj ciąg, który zaczyna się od, ]a następnie rób non-zachłanny, .*?dopóki nie trafisz specjalnego znaku kontrolnego o nazwie „znak alarmu (dzwonek)”
Peter Nore
źródło
1
Nadal muszę wymyślić, jak to zrobić, ale to naprawdę działa;)
asdmin,
@asdmin - Zasadniczo Odzwierciedla to wyjście typescriptz perlprogramu, który usuwa pewne znaki sterujące z wyjścia, a następnie rury wyjście do uniksowego colpolecenia, którego -bopcja usuwa wszystkie „Usuń” kluczowe artefakty w transkryptu. Następnie przesyła dane wyjściowe do pliku tekstowego.
Peter Nore,
Dla mnie to koduje wynik w pierwszym wierszu maszynopisu, ale jest najlepszą odpowiedzią.
Alex
Wydaje się, że działa to bardzo dobrze w przypadku niektórych maszynopisów; z pewnością jest bardziej czytelny niż wynik uzyskany przez zaakceptowaną odpowiedź.
fakedad
legendarna odpowiedź!
zack,
2

Dla dużej ilości scriptwyników zhakowałbym iteracyjnie skrypt perla. W przeciwnym razie edytuj ręcznie za pomocą dobrego edytora.

Jest mało prawdopodobne, aby istniała zautomatyzowana metoda usuwania znaków kontrolnych z scriptdanych wyjściowych w sposób, który odtwarza to, co było wyświetlane na ekranie w pewnych ważnych momentach (na przykład, gdy host czekał na pierwszy znak wprowadzony przez użytkownika).

Na przykład ekran może być pusty, z wyjątkiem tego Andrew $, że jeśli następnie wpiszesz rm /*i naciśniesz backspace dwanaście razy (znacznie więcej niż to konieczne), to, co zostanie wyświetlone na ekranie, zależy od tego, która powłoka była uruchomiona, jakie są twoje obecne sttyustawienia ( które możesz zmienić w trakcie sesji) i prawdopodobnie także inne czynniki.

Powyższe dotyczy każdej zautomatyzowanej metody ciągłego przechwytywania danych wejściowych i wyjściowych. Główną alternatywą jest robienie „zrzutów ekranu” lub wycinanie i wklejanie ekranu w odpowiednim czasie podczas sesji (to jest to, co robię dla instrukcji użytkownika, notatek z dziennego dziennika itp.).

RedGrittyBrick
źródło
2

Użyłem, cat filenamektóry usuwa znaki kontrolne :-)

Peeyush
źródło
imo to ładniejsza odpowiedź, ponieważ naprawdę usuwa wszystkie znaki kontrolne.
Nathanael Farley
w OSX kot nie usuwa znaków sterujących kolorem ...
Nick
9
W rzeczywistości cat w ogóle nie usuwa znaków kontrolnych, raczej wypisuje je dosłownie, a terminal interpretuje je. Może to działać dla Ciebie, jeśli Twój maszynopis jest krótki w stosunku do bufora terminala i możesz po prostu skopiować i wkleić z terminala. Nie tak dobrze, jeśli twój maszynopis jest duży.
mc0e,
1
Zgoda. To niczego nie usuwa. Po prostu pozwala powłoce na ich interpretację. Nadal są obecne.
Kentgrav,
2

Jeśli chcesz nagrać swoje polecenia (np. Aby później przekształcić je w skrypt bash), to rozsądnym włamaniem jest uruchomienie script(1), a następnie uruchomienie go

bash -x

Następnie grepplik wyjściowy (zwykle „maszynopis”) szuka linii zaczynających się od „+”. Wyrażenie regularne załatwi ^\+sprawę.

Yaron
źródło
2

Jeśli chcesz zapisać dane wyjściowe w pliku:

col -bp < typescript >>newfile

w razie potrzeby użyj komendy unix2dos, aby przekonwertować plik do formatu Windows

amara
źródło
1
W Ubuntu 14.04 pozostawia wiele śmieci na początku i na końcu linii. Całkiem czytelny, ale niezbyt czysty.
mc0e,
2

col -bp przetwarza backspace zgodnie z potrzebami (AFAIK). Ale zmienia sekwencje ucieczki kolorów. Dobrze jest najpierw usunąć sekwencje kolorów, a następnie, jeśli to możliwe, przetworzyć odstępy.

Jest to bardzo powszechna potrzeba i jestem zaskoczony, że nie ma już więcej rozwiązań. Skryptowanie sesji jest niezwykle powszechne, wtedy ktoś musi przejrzeć procedurę. Chcesz wyciąć wszystkie małe błędy pisarskie i sekwencje specjalne kolorów, aby utworzyć „czysty” skrypt procedury do wykorzystania w przyszłości. Preferowany prosty tekst ASCII. Myślę, że właśnie to jest zamierzone przez „czytelne dla człowieka” i jest to bardzo rozsądne.

Aaron
źródło
1

Znalazłem odpowiedź udzieloną przez dewtall na podobne pytanie na tablicy Unixa, która jest bardziej skuteczna w usuwaniu znaków kontrolnych z wyników skryptu, jeśli jesteś w środowisku, w którym dostępny jest Perl.

skrypt dewtall:

#!/usr/bin/perl
while (<>) {
    s/ \e[ #%()*+\-.\/]. |
       \r | # Remove extra carriage returns also
       (?:\e\[|\x9b) [ -?]* [@-~] | # CSI ... Cmd
       (?:\e\]|\x9d) .*? (?:\e\\|[\a\x9c]) | # OSC ... (ST|BEL)
       (?:\e[P^_]|[\x90\x9e\x9f]) .*? (?:\e\\|\x9c) | # (DCS|PM|APC) ... ST
       \e.|[\x80-\x9f] //xg;
       1 while s/[^\b][\b]//g;  # remove all non-backspace followed by backspace
    print;
}

Aby usunąć znaki kontrolne:

./dewtalls-script.pl < output-from-script-that-needs-control-characters-removed
rynemccall
źródło
1

https://github.com/RadixSeven/typescript2txt został napisany w celu rozwiązania tego problemu.

Minęły 4 lata, odkąd ostatnio go zaktualizowałem / użyłem, ale nie pamiętam, żeby robić coś wymyślnego, co nie powinno dziś działać.

Tytułowy
źródło
0

Znalazłem dobry sposób, aby to zrobić. W moim systemie długie linie wyjściowe są posypane „^ M” (puste miejsce, po którym następuje powrót karetki). „^ M” można ładnie zastąpić znakiem zerowym „^ @”, który w ogóle nie wyświetla się podczas przechwytywania pliku.

Przechwytuję też timing, więc aby idealnie odtworzyć plik, nie mogę po prostu całkowicie usunąć „^ M” za pomocą poniższych poleceń (ponieważ odtwarzanie skryptów liczy bajty):

tr '\r' '\0' | sed 's/ \x0//g'

Uruchamiam polecenie skryptowe w następujący sposób:

script -t -f session.log 2>timing

Później robię:

cat session.log | tr '\r' '\0' > typescript 
scriptreplay -t timing | sed 's/ \x0//g'

Pierwsza edycja (przed powtórzeniem) zachowuje liczbę bajtów w pliku. Druga edycja (po powtórce) usuwa białe miejsca w losowych miejscach. (Zauważ, że domyślnie scriptreplay szuka pliku wejściowego o nazwie „maszynopis”, dlatego nie dostarczyłem go po „timingu”).

Khanan
źródło
-1

dos2unix na wyjściu również załatwi sprawę

Albert
źródło
7
Czy możesz wyjaśnić, jak go użyć do wykonania zadania?
Ben N
-1

Innym rozwiązaniem jest użycie, stringsktóre wypisuje tylko drukowalne znaki z pliku (lub ze standardowego wejścia):

strings -n 1 filename

Ta -n 1opcja ustawia minimalną długość sekwencji do zachowania na jedną, a tym samym zapewnia zachowanie nawet pojedynczych znaków drukowalnych otoczonych znakami niedrukowalnymi.

Jednym z możliwych wad tego podejścia jest to, że stringsdodaje podziały linii między ciągłymi ciągami znaków do wydrukowania. Na przykład plik z zawartością

Foo<SOMECONTROLCHAR>Bar

(gdzie <SOMECONTROLCHAR>jest znak kontrolny lub dowolny inny znak niedrukowalny) zostanie zwrócony jako

Foo
Bar

Innym zagadnieniem poruszonym w komentarzach jest to, że niektóre sekwencje znaków kontrolnych składają się z kombinacji zarówno znaków drukowalnych, jak i niedrukowalnych, a takie podejście usunęłoby tylko część z nich.

Jednak stringsdobrze sprawdza się w usuwaniu znaków kontrolnych, takich jak backspace wspomniany w pytaniu.

justfortherec
źródło
stringsnie usuwa wszystkich znaków niedrukowalnych. Identyfikuje i drukuje sekwencje znaków do wydrukowania . To nie to samo.
CVn
@ MichaelKjörling, masz rację, domyślnie stringsdrukowane są tylko sekwencje o minimalnej długości 4. Poprawiłem swoją odpowiedź, dodając -n 1opcję, która ustawia minimalną długość na 1. Dziękujemy za zwrócenie na to uwagi.
justfortherec
Odpowiedź nadal zawiera to samo twierdzenie, które stringsusuwa wszystkie niedrukowalne znaki, więc nadal jest błędne w taki sam sposób, jak przed edycją. Jest również oczywiście zepsuty, ponieważ „niektóre kody kolorów” (i ogólnie kody kontrolne) często składają się zarówno ze znaków drukowalnych, jak i niedrukowalnych. Na przykład sekwencją kodu sterującego do zmiany koloru tekstu może być miejsce, w ESC[01;52mktórym ESCznajduje się pojedynczy znak zmiany znaczenia (wartość bajtu 27). Użycie stringszgodnie z sugestią pozostawiłoby [01;52mwynik, co nie ma znaczenia.
CVn
Dobra uwaga, @ MichaelKjörling. Zwłaszcza przykład z kodem koloru był bardzo niefortunny. Dzięki za pomoc w poprawieniu mojej odpowiedzi. Czy zmiany odpowiednio uwzględniają Twoje obawy? stringsmoże nie wykonywać tej samej pracy, co niektóre inne odpowiedzi, ale IMHO to prawidłowe podejście do rozwiązania problemu opisanego w pytaniu.
justfortherec