Come ripulire l'output del comando "script" di Linux


35

Sto usando il comando 'script' di Linux http://www.linuxcommand.org/man_pages/script1.html per tracciare alcune sessioni interattive. I file di output che contengono caratteri non stampabili, inclusi i tasti premuti sul backspace.

C'è un modo per riordinare questi file di output in modo che contengano solo ciò che è stato visualizzato sullo schermo?

Oppure c'è un altro modo per registrare una sessione di shell interattiva (input e output)?


"O c'è un altro modo per registrare una sessione di shell interattiva (input e output)?" Conosci asciinema.org ?
masterxilo,

Risposte:


34

Se si desidera visualizzare il file, è possibile inviare l'output tramite col -bp; questo interpreta i caratteri di controllo. Quindi puoi passare meno, se vuoi.

col -bp typescript | less -R

Su alcuni sistemi colnon accetterebbe un argomento nomefile, utilizzare invece questa sintassi:

col -bp <typescript | less -R

1
sul mio sistema, colnon accetterei un nome file, quindi ho fatto col -bp < typescript e ottenuto quello che volevo.
Andrew

Non funziona per me, rimescola parte dell'output.
Alex,

1
Sul mio sistema less -Rda solo fornisce un output migliore rispetto al col -bpprimo piping .
Brian Hawkins,

@BrianHawkins Concordo. L'uso col -bp <typescript | less -Rnon visualizza la console colorata. L'utilizzo less -R typescriptmostra la console colorata!
Trevor Boyd Smith,

questo è utile solo se si desidera visualizzare lo script in modo interattivo less.
Trevor Boyd Smith,

18
cat typescript | perl -pe 's/\e([^\[\]]|\[.*?[a-zA-Z]|\].*?\a)//g' | col -b > typescript-processed

ecco qualche interpretazione dell'input della stringa per perl:

  • s/pattern//gsignifica fare una sostituzione sull'intero (l' gopzione significa fare l'intera cosa invece di fermarsi sul primo sostituto) stringa di input

ecco qualche interpretazione del modello regex:

  • \e corrisponde allo speciale carattere di controllo "escape" (ASCII 0x1A)
  • (e )sono l'inizio e la fine di un gruppo
  • |significa che il gruppo può abbinare uno di N pattern. dove sono gli schemi N
    • [^\[\]] o
    • \[.*?[a-zA-Z] o
    • \].*?\a
  • [^\[\]] si intende
    • abbina una serie di caratteri NOT in cui i caratteri non sono [e]
  • \[.*?[a-zA-Z] si intende
    • abbinare una stringa che inizia con [quindi fare un non avido .*?fino al primo carattere alfa
  • \].*?\a si intende
    • abbina una stringa che inizia con ]quindi fai un non avido .*?fino a quando non colpisci lo speciale carattere di controllo chiamato "il carattere di avviso (campana)"

1
Devo ancora capire come, ma funziona davvero;)
asdmin,

@asdmin - Fondamentalmente, questo fa eco all'output di typescriptun perlprogramma che rimuove determinati caratteri di controllo dall'output, quindi reindirizza l'output al colcomando unix , la cui -bopzione rimuove eventuali artefatti chiave "cancella" nella trascrizione. Quindi invia l'output a un file di testo.
Peter Nore,

Questo confonde l'output nella prima riga del dattiloscritto per me, ma è la risposta migliore.
Alex,

Questo sembra funzionare molto bene con alcuni dattiloscritti; è certamente più leggibile dell'output prodotto dalla risposta accettata.
fakedad

risposta leggendaria!
zack

2

Per una grande quantità di scriptoutput, hackererei uno script perl insieme in modo iterativo. Altrimenti modifica a mano con un buon editor.

È improbabile che esista un metodo automatizzato esistente per rimuovere i caratteri di controllo scriptdall'output in un modo che riproduca ciò che è stato visualizzato sullo schermo in determinati momenti importanti (come quando l'host stava aspettando il primo carattere di alcuni input dell'utente).

Ad esempio, lo schermo potrebbe essere vuoto tranne che Andrew $, se hai digitato rm /*e premuto backspace dodici volte (molto più del necessario), ciò che viene mostrato sullo schermo alla fine dipende da quale shell era in esecuzione, quali sono le tue sttyimpostazioni attuali ( che potresti cambiare nel corso di una sessione) e probabilmente anche altri fattori.

Quanto sopra si applica a qualsiasi metodo automatizzato di acquisizione continua di input e output. L'alternativa principale è scattare "schermate" o tagliare e incollare lo schermo nei momenti appropriati durante la sessione (che è quello che faccio per le guide per l'utente, le note per un diario giornaliero, ecc.).



2

Ho usato cat filenameche rimuove i caratteri di controllo :-)


imo questa è una risposta migliore, poiché rimuove davvero tutti i caratteri di controllo.
Nathanael Farley,

su OSX, cat non rimuove i caratteri di controllo colore ...
Nick,

9
In realtà cat non rimuove affatto i caratteri di controllo, piuttosto li emette testualmente e il terminale li interpreta. Ciò potrebbe funzionare per te se il tuo dattiloscritto è breve rispetto al buffer del terminale e puoi semplicemente copiare e incollare dal terminale. Non così buono se il tuo dattiloscritto è grande però.
mc0e,

1
Concordato. Questo non rimuove nulla. Permette semplicemente alla shell di interpretarli. Sono ancora presenti
Kentgrav,

2

Se quello che stai cercando è registrare i tuoi comandi (ad es. Per trasformarli successivamente in uno script bash), allora deve essere eseguito un hack ragionevole script(1), quindi al suo interno esegui

bash -x

Successivamente grepil file di output (di solito "dattiloscritto") cerca le righe che iniziano con un "+". L'espressione regolare ^\+farà il trucco.


2

Se si desidera scrivere l'output in un file:

col -bp < typescript >>newfile

utilizzare il comando unix2dos per convertire il file in formato Windows, se lo si desidera


1
Su Ubuntu 14.04, questo lascia molta spazzatura all'inizio e alla fine delle righe. Piuttosto leggibile, ma non molto pulito.
mc0e,

2

col -bp elabora i backspaces come desiderato (AFAIK). Ma altera le sequenze di escape del colore. Potrebbe essere utile rimuovere prima le sequenze di colori, quindi, se possibile, elaborare i backspaces.

Questa è un'esigenza molto comune e sono sorpreso che non ci siano più soluzioni. È estremamente comune scrivere una sessione, quindi qualcuno ha bisogno di rivedere la procedura. Volete eliminare tutti i piccoli errori di battitura e le sequenze di escape del colore per creare uno script "pulito" della procedura per riferimento futuro. Preferisce un semplice testo ASCII. Penso che questo sia ciò che si intende per "lettura umana", ed è una cosa molto ragionevole da fare.


1

Ho trovato la risposta che dewtall ha fornito a una domanda simile sulla scheda Unix per essere più efficace nel rimuovere i caratteri di controllo dall'output dello script se ci si trova in un ambiente in cui Perl è disponibile.

sceneggiatura di 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;
}

Per rimuovere i caratteri di controllo:

./dewtalls-script.pl < output-from-script-that-needs-control-characters-removed


0

Ho trovato un buon modo per farlo. Sul mio sistema, le linee di uscita lunghe sono cosparse di "^ M" (spazio vuoto seguito da ritorno a capo). "^ M" può essere facilmente sostituito con il carattere null "^ @", che non viene visualizzato affatto quando si esegue il cat del file.

Catturo anche i tempi, quindi per poter riprodurre perfettamente il file, non posso semplicemente rimuovere completamente "^ M" usando i seguenti comandi (perché la sceneggiatura conta i byte):

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

Eseguo il mio comando di script in questo modo:

script -t -f session.log 2>timing

Quindi, quello che faccio dopo è:

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

La prima modifica (prima della riproduzione) mantiene il numero di byte nel file. La seconda modifica (dopo il replay) elimina lo spazio bianco in punti casuali. (Si noti che per impostazione predefinita lo scriptreplay cerca il file di input denominato "typescript", motivo per cui non l'ho fornito dopo "timing".)


-1

dos2unix sull'output farà anche il trucco


7
Potresti spiegare come usarlo per svolgere il compito?
Ben N

-1

Un'altra soluzione consiste nell'utilizzare stringsche stampa solo caratteri stampabili da un file (o dallo standard input):

strings -n 1 filename

L' -n 1opzione imposta la lunghezza minima delle sequenze da conservare su una e quindi assicura che vengano conservati anche i singoli caratteri stampabili circondati da caratteri non stampabili.

Un possibile aspetto negativo di questo approccio è che stringsaggiunge interruzioni di riga tra stringhe contigue di caratteri stampabili. Ad esempio un file con contenuto

Foo<SOMECONTROLCHAR>Bar

(dove <SOMECONTROLCHAR>è il carattere di controllo o qualsiasi altro carattere non stampabile) verrebbe restituito come

Foo
Bar

Un altro problema sollevato nei commenti è che alcune sequenze di caratteri di controllo consistono in una combinazione di caratteri sia stampabili che non stampabili e questo approccio rimuoverà solo parte di quelli.

Tuttavia, stringsfa un buon lavoro nel rimuovere i caratteri di controllo come il backspace menzionato nella domanda.


stringsnon rimuove tutti i caratteri non stampabili. Identifica e stampa sequenze di caratteri stampabili . Questa non è la stessa cosa.
un CVn

@ MichaelKjörling, hai ragione, per impostazione predefinita stringsstampa solo sequenze di una lunghezza minima di 4. Ho corretto la mia risposta aggiungendo l' -n 1opzione che imposta la lunghezza minima a 1. Grazie per averlo sottolineato.
justfortherec,

La risposta fa ancora la stessa affermazione che stringsrimuove tutti i caratteri non stampabili, quindi è ancora errata nello stesso modo in cui era prima della modifica. Ovviamente è anche rotto perché "alcuni codici colore" (e codici di controllo in generale) sono spesso costituiti sia da caratteri stampabili che non stampabili. Ad esempio, una sequenza di codici di controllo per modificare il colore del testo potrebbe essere ESC[01;52mdove si ESCtrova il carattere di escape singolo (valore byte 27). L'uso stringscome suggerito lascerebbe [01;52mnell'output, il che non ha senso.
un CVn

Buon punto, @ MichaelKjörling. Soprattutto l'esempio con il codice colore è stato molto sfortunato. Grazie per avermi aiutato a migliorare la mia risposta. Le modifiche affrontano le tue preoccupazioni in modo appropriato? stringspotrebbe non fare lo stesso lavoro di alcune delle altre risposte, ma IMHO è un approccio valido per risolvere il problema descritto nella domanda.
justfortherec,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.