Entfernen von Steuerzeichen (einschließlich Konsolencodes / -farben) aus der Skriptausgabe

68

Ich kann den Befehl "script" verwenden, um eine interaktive Sitzung in der Befehlszeile aufzuzeichnen. Dies schließt jedoch alle Steuerzeichen und Farbcodes ein. Ich kann Steuerzeichen (wie die Rücktaste) mit "col -b" entfernen, aber ich kann keinen einfachen Weg finden, um die Farbcodes zu entfernen.

Beachten Sie, dass ich die Befehlszeile wie gewohnt verwenden möchte, also keine Farben dort deaktivieren möchte - ich möchte sie nur aus der Skriptausgabe entfernen. Ich weiß auch, dass ich herumspielen und versuchen kann, einen regulären Ausdruck zu finden, um das Problem zu beheben, aber ich hoffe, dass es eine einfachere (und zuverlässigere - was ist, wenn es einen Code gibt, über den ich bei der Entwicklung des regulären Ausdrucks nichts weiß?) Lösung gibt.

So zeigen Sie das Problem:

spl62 tmp: script
Skript gestartet, Datei ist Typenskript
spl62 lepl: ls
add-licence.sed build-example.sh commit-test push-docs.sh
add-licence.sh build.sh delete-licence.sed setup.py
asn build-test.sh delete-licence.sh src
build-doc.sh sauber doc-src test.ini
spl62 lepl: Ausfahrt
Skript fertig, Datei ist Typoskript
spl62 tmp: cat -v Typoskript
Skript gestartet am Do 09 Jun 2011 09:47:27 CLT
spl62 lepl: ls ^ M
^ [0m ^ [00madd-licence.sed ^ [0m ^ [00; 32mbuild-example.sh ^ [0m ^ [00mcommit-test ^ [0m ^ [00; 32mpush-docs.sh ^ [[0m ^ M
^ [[00; 32m ^ [00; 32mbuild.sh ^ [[0m ^ [[00mdelete-licence.sed ^ [[0m ^ [[00msetup.py ^ [[0m ^ M
^ [[01; 34m ^ [[0m ^ [[00; 32m ^ M
^ [[00; 32mbuild-doc.sh ^ [[0m ^ [[00; 32mclean ^ [[0m ^ [[01; 34mdoc-src ^ [[0m ^ [[00mtest.ini ^ [[0m ^ M
spl62 lepl: Ausfahrt ^ M

Skript erstellt am Do 09 Jun 2011 09:47:29 CLT
spl62 tmp: col -b <Typoskript 
Skript gestartet am Do 09 Jun 2011 09:47:27 CLT
spl62 lepl: ls
0m00madd-licence.sed0m 00; 32mbuild-example.sh0m 00mcommit-test0m 00; 32mpush-docs.sh0m
00; 32madd-licence.sh0m 00; 32mbuild.sh0m 00mdelete-licence.sed0m 00msetup.py0m
01; 34masn0m 00; 32mbuild-test.sh0m 00; 32mdelete-licence.sh0m 01; 34msrc0m
00; 32mbuild-doc.sh0m 00; 32mclean0m 01; 34mdoc-src0m 00mtest.ini0m
spl62 lepl: Ausfahrt

Skript erstellt am Do 09 Jun 2011 09:47:29 CLT
Andrew Cooke
quelle

Antworten:

57

Das folgende Skript sollte alle ANSI / VT100 / xterm-Steuersequenzen herausfiltern (basierend auf ctlseqs ). Bei minimalem Test melden Sie bitte ein zu geringes oder zu hohes Spiel.

#!/usr/bin/env perl
## uncolor — remove terminal escape sequences such as color changes
while (<>) {
    s/ \e[ #%()*+\-.\/]. |
       \e\[ [ -?]* [@-~] | # CSI ... Cmd
       \e\] .*? (?:\e\\|[\a\x9c]) | # OSC ... (ST|BEL)
       \e[P^_] .*? (?:\e\\|\x9c) | # (DCS|PM|APC) ... ST
       \e. //xg;
    print;
}

Bekannte Probleme:

  • Beschwert sich nicht über fehlerhafte Sequenzen. Dafür ist dieses Skript nicht gedacht.
  • Mehrzeilige Zeichenfolgenargumente für DCS / PM / APC / OSC werden nicht unterstützt.
  • Bytes im Bereich 128–159 können als Steuerzeichen analysiert werden, obwohl dies selten verwendet wird. Hier ist eine Version, die Nicht-ASCII-Steuerzeichen analysiert (dies wird Nicht-ASCII-Text in einigen Codierungen, einschließlich UTF-8, entstellen).
#!/usr/bin/env perl
## uncolor — remove terminal escape sequences such as color changes
while (<>) {
    s/ \e[ #%()*+\-.\/]. |
       (?:\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;
    print;
}
Gilles
quelle
danke an beide antworten. Ich dachte, ich sollte etwas als gute Antwort geben, obwohl beide reguläre Ausdrücke geben, die ich vermeiden wollte. wählte dieses, da es eine Referenz für das Format gibt.
Andrew Cooke
@andrew: Mein regulärer Ausdruck ist so flexibel, dass ich davon ausgehe, dass er mit so gut wie jedem bereits vorhandenen Terminal und wahrscheinlich auch mit jedem bereits vorhandenen Terminal von morgen funktioniert. Ich habe es nicht viel getestet, daher kann es zu Fehlern kommen, aber der Ansatz ist solide, da die Steuersequenzen einigen allgemeinen Mustern folgen.
Gilles
Bitte geben Sie an, wie dieses Skript verwendet wird. Benötigt es Rohreingabe? oder Positionsargumente?
Trevor Boyd Smith
@ TrevorBoydSmith Entweder funktioniert die Eingabe, und die Ausgabe erfolgt wie bei typischen Textdienstprogrammen immer über die Standardausgabe.
Gilles
Dadurch werden Multibyte-Zeichen wie ☺ (\ xe2 \ x98 \ xba) zerkleinert. Die [\ x80- \ x9f] -Klausel entfernt das mittlere Byte.
Jeffrey
31

Aktualisieren der Antwort von Gilles, um auch Zeilenumbrüche zu entfernen und vorherige Zeichen mit der Rücktaste zu löschen, die mir für ein in Cygwin generiertes Typoskript wichtig waren:

#!/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;
}
dewtell
quelle
+1 Ich habe bereits einen Beitrag mit der gleichen Frage wie das OP geschrieben, als ich diese Nachricht mit Ihrem Skript und der von @Gilles gefunden habe. +1 für euch beide
miracle173
10

Ich würde sedin diesem Fall verwenden.

machen:

cat -v typescript | sed -e "s/\x1b\[.\{1,5\}m//g"

sed -e "s / search / replace / g" ist Standard. Der reguläre Ausdruck wird wie folgt erklärt:

\x1bstimmen Sie mit der Escape-Taste überein, bevor der Farbcode \[mit der ersten offenen Klammer .\{1,5\}1 bis 5 eines einzelnen Zeichens übereinstimmt. Müssen Sie \die geschweiften Klammern, um die Schale davon abzuhalten, sie zu zerfleischen. mLetztes Zeichen in Regex - folgt normalerweise dem Farbcode. //leere Zeichenfolge, durch die alles ersetzt werden soll. gstimmen Sie es mehrmals pro Zeile ab.

Ruhmkröte
quelle
3
Diese Regex Streifen zu viel ( foo\e[1m(1m = {wird foo = {statt foo(m = {), ersetzt .durch [0-9;]ist genauer.
Lekensteyn
Ersetzen Sie dies .\{1,5\}durch [^m]\{1,5\}- aber beachten Sie auch, dass dadurch immer noch nur "Grafikwiedergabecodes" (die mit einem enden m) entfernt werden - im Grunde genommen Farb-, Umkehr-, Fett- und Kursivstile (sofern zutreffend).
Hannu
Dies wird nicht entfernt \x1b(B(in Rusts Farbausgabe enthalten)
ideasman42
1
Warum ist es \x1bund nicht \033?
Reife
Es könnte \u001bstatt\x1b
23.
9
cat typescript | perl -pe 's/\e([^\[\]]|\[.*?[a-zA-Z]|\].*?\a)//g' | col -b > typescript-processed
Peter Nore
quelle
6
# The "sed -r" trick does not work on every Linux, I still dunno why:
DECOLORIZE='eval sed "s,${END}\[[0-9;]*[m|K],,g"'

=> wie benutzt man:

<commands that type colored output> | ${DECOLORIZE}

Getestet unter: - AIX 5.x / 6.1 / 7.1 - Linux Mandrake / Mandriva / SLES / Fedora - SunOS

Assgeier
quelle
3

Ich löste das Problem, indem ich scriptreplayauf einem Bildschirm lief und den Scrollback-Puffer in eine Datei abspeicherte.

Das folgende Expect-Skript erledigt dies für Sie.

Es wurde auf Logfiles mit bis zu 250.000 Zeilen getestet. Im Arbeitsverzeichnis benötigen Sie Ihr Scriptlog, eine Datei mit dem Namen "time" mit dem 10.000.000-fachen der Zeile "1 10" und das Script. Ich brauche den Namen Ihrer Skriptdatei als Kommandozeilenargument, wie ./name_of_script name_of_scriptlog.

#!/usr/bin/expect -f 

set logfile [lindex $argv 0]

if {$logfile == ""} {puts "Usage: ./script_to_readable.exp \$logfile."; exit}

set timestamp [clock format [clock sec] -format %Y-%m-%d,%H:%M:%S]
set pwd [exec pwd]
if {! [file exists ${pwd}/time]} {puts "ERROR: time file not found.\nYou need a file named time with 10.000.000 times the line \"1 10\" in the working directory for this script to work. Please provide it."; exit}
set wc [exec cat ${pwd}/$logfile | wc -l]
set height [ expr "$wc" + "100" ]
system cp $logfile ${logfile}.tmp
system echo $timestamp >> ${logfile}.tmp
set timeout -1
spawn screen -h $height -S $timestamp 
send "scriptreplay -t time -s ${logfile}.tmp 100000 2>/dev/null\r"
expect ${timestamp} 
send "\x01:hardcopy -h readablelog.${timestamp}\r"

send "exit\r"

system sed '/^$/d' readablelog.$timestamp >> readablelog2.$timestamp
system head -n-2 readablelog2.$timestamp >> ${logfile}.readable.$timestamp
system rm -f readablelog.$timestamp readablelog2.$timestamp ${logfile}.tmp

Die Zeitdatei kann von generiert werden

for i in $(seq 1 10000000); do echo "1 10" >> time; done
hnkchnsk
quelle
Der Befehl zum Generieren einer Zeitdatei erzeugte einige Minuten lang eine 100% ige CPU-Auslastung. Nach Beendigung der Auslastung lag meine Speicherauslastung bei 100%, und der ausgeführte Befehl führte zu "Verzweigung: Speicher kann nicht zugeordnet werden". Und es hat nicht wirklich wie erwartet funktioniert.
barteks2x
Es gibt eine viel einfachere Möglichkeit, die Timing-Datei zu generieren. Die Felder sind " delay blocksize", es gibt also keinen Grund, es nicht einfach " 0 <entirefile>" zu machen und das Ganze ohne Verzögerung zu löschen. Sie können dies tun, indem Sie die Größe des Skripts abzüglich der ersten Zeile ( tail -n +2 typescript|wc -c) nehmen und die Timing-Datei mit erstellen echo "0 "`tail -n +2 typescript|wc -c` > timing. Das ist im Grunde genommen sofort und spielt scriptreplaydas gesamte Skript mit der schnellstmöglichen Geschwindigkeit ab.
FeRD
1

Ich habe diese Frage gefunden, als ich nach einer Lösung für das gleiche Problem gesucht habe. Ein bisschen mehr Graben und fand dieses Skript bei Live Journal unter diesem Link. Ich habe perfekt für mich gearbeitet. Es ist auch eine sehr gute Beschreibung dieses Problems und der Funktionsweise der Lösung. Auf jeden Fall eine Lektüre wert. http://jdimpson.livejournal.com/7040.html

#!/usr/bin/perl -wp

# clean up control characters and other non-text detritus that shows up 
# when you run the "script" command.

BEGIN {
# xterm titlebar escape sequence
$xtermesc = "\x1b\x5d\x30\x3b";

# the occurence of a backspace event (e.g. cntrl H, cntrol W, or cntrl U)
$backspaceevent = "\x1b\\\x5b\x4b"; # note escaping of third character

# ANSI color escape sequence
$ansiesc = qr/\x1b\[[\d;]*?m/;

# technically, this is arrow-right. For some reason, being used against
# very long backspace jobs. I don't fully understand this, as evidenced
# by the fact that is off by one sometimes.
$bizarrebs = qr/\x1b\[C/;

# used as part of the xterm titlebar mechanism, or when
# a bell sounds, which might happen when you backspace too much.
$bell = "\x07"; # could use \a

$cr = "\x0d"; # could use \r

$backspace = "\x08"; # could use \b
}

s/$xtermesc.+?$bell//g;
s/[$cr$bell]//g;
s/${backspaceevent}//g;
s/$ansiesc//g;
while (s/(.)(?=$backspace)//) { s/$backspace//; } # frickin' sweet 
# For every ^H delete the character immediately left of it, then delete the ^H.
# Perl's RE's aren't R, so I wonder if I could do this in one expression.
while (s/(..)(?=$bizarrebs)//) { s/$bizarrebs//; }
SammerV
quelle
1

Ich würde es vorziehen, spezielle Tools zu verwenden, um die Skriptausgabe über benutzerdefinierte reguläre Ausdrücke in einfachen Text zu konvertieren, der ständig unterstützt und getestet wird. Das hat also für mich funktioniert:

$ cat typescript | ansi2txt | col -bp > typescript.txt.bp    
$ cat -v typescript.txt.bp

Skriptbefehl erfasst in Typoskriptdatei ansi2txt - konvertiert Ansi-Code mit Escapezeichen wie Farbcodes, Leerzeichen usw. in regulären Text. Allerdings habe ich festgestellt, dass ein paar Escapezeichen noch übrig sind. col -bp - hat sie vollständig entfernt.

Ich habe dies auf der neuesten Ubuntu-Disco getestet und es funktioniert.

Dmytro Brazhnyk
quelle
1

Das Paket enthält einen ansi2txtBefehl colorized-logsfür Ubuntu. Es entfernt ANSI-Farbcodes in netter Weise, geht aber nicht auf Fortschrittsbalken ein, die durch das Aussenden von Zeichen ^Hoder ^Mdas Überschreiben von vorhandenem Text erzeugt werden. col -bkann beschäftigen diejenigen , so für die besten Ergebnisse , die Sie kombinieren die beiden können

cat typescript | ansi2txt | col -b
Marius Gedminas
quelle
0

Ich stellte fest, dass nur die Verwendung catvon alles war, was ich brauchte, um die Ausgabe von scriptim Terminal anzuzeigen . Dies hilft nicht , wenn die Ausgabe in einer anderen Datei umleiten, aber das Ergebnis lesbar macht, im Gegensatz zu cat -v, col -boder ein Texteditor.

Um Farben zu entfernen oder die Ergebnisse in einer Datei zu speichern, kopieren Sie die Ausgabe manuell und fügen Sie sie catin einen Texteditor oder in einen anderen catBefehl ein.

cat > endResult << END
<paste_copied_text_here>
END
Roger Dueck
quelle
1
Hat Ihr scriptLauf eine Ausgabe mit angehängten Farbcodes enthalten, wie im Fall des OP?
Jeff Schaller
Mit catpräsentiert die Originalfarben, die durch manuelles Kopieren und Einfügen entfernt werden können. Das OP verwendet cat -vund col -b, wobei beide Codes anstelle eines ordnungsgemäß formatierten Endergebnisses vorhanden sind. Ich habe meine Antwort bearbeitet.
Roger Dueck
-2

Verfolgung der letzten Antwort, die tr und verwendet: cntrl: könnten wir vielleicht tun

sed "/^[[:cntrl:]]/d" output.txt

Dies scheint für mich zu funktionieren, da alle von vi erzeugten Zeilen mit einem Steuerzeichen beginnen. Es passiert auch, dass leere Zeilen und Zeilen, die mit einem Tabulator beginnen, entfernt werden, obwohl das für das funktioniert, was ich tue. Möglicherweise gibt es eine Möglichkeit, ein Steuerzeichen mit Ausnahme von \ n \ m \ t abzugleichen.

Vielleicht können wir nach dem bestimmten Steuerzeichen suchen, und es sieht so aus, als ob alle von vi erzeugten Junk-Zeilen mit ^ [beginnen. hexdump sagt mir, dass das erste Zeichen 1b ist, also scheint das auch zu funktionieren

sed "/^\x1b/d" output.txt

Dies ähnelt einer oben angegebenen Antwort, funktioniert jedoch nicht ordnungsgemäß, da nach dem Ausführen des Befehls der Befehlszeile bereits Junk-Zeichen hinzugefügt wurden, als hätte der Benutzer sie eingegeben.

Snaran
quelle
1
Es gibt keine "letzte Antwort", da die Antworten die Reihenfolge ändern können und müssen. Verwenden Sie die Schaltfläche "Teilen" unter der Antwort, auf die Sie verweisen möchten, und fügen Sie diese als Link in Ihre Antwort ein. Vorausgesetzt, Ihre Antwort ist mehr als nur ein Kommentar. Im Moment kann ich nicht identifizieren, auf welche der verschiedenen Antworten Sie sich beziehen.
Roaima
1
"Könnten wir vielleicht tun ..." Ja, wir könnten das tun - aber es würde jede Zeile löschen , die mit einem Steuerzeichen beginnt . Bei der Ausgabe von ls --color(wie in der Frage gezeigt) löscht Ihre Lösung beispielsweise fast jede Zeile, die Informationen enthält. Nicht gut. Aber danke, dass du den nutzlosen Gebrauch von weggelassen hast cat. :-) ⁠
G-Man
Gibt es eine Möglichkeit, eine Zeichenklasse zu erstellen, die lautet: iscntrl: aber nicht: isspace :? Vielleicht eine Syntax wie ^ [[: iscntrl:] - [: isspace]]
snaran
-4

tr - Zeichen übersetzen oder löschen

cat typescript | tr -d [[:cntrl:]]
Chunk
quelle
Willkommen bei Unix Stackexchange! Wenn Sie eine Antwort geben, ist es vorzuziehen, eine Erklärung zu geben , warum Ihre Antwort die richtige ist.
Stephen Rauch
Kürze ist akzeptabel, aber ausführlichere Erklärungen sind besser. , löst das Problem auch hier nicht ganz.
Kusalananda
3
Dies wird tatsächlich nicht richtig funktionieren, da es beispielsweise kein entfernt 01;34mund das Zeilenende entfernt newline (\n).
Sorontar