ANSI-Farbcodes aus dem Textstrom entfernen


73

Untersuchen der Ausgabe von

perl -e 'use Term::ANSIColor; print color "white"; print "ABC\n"; print color "reset";'

In einem Texteditor (z. B. vi) wird Folgendes angezeigt:

^[[37mABC
^[[0m

Wie würde man die ANSI-Farbcodes aus der Ausgabedatei entfernen? Ich nehme an, der beste Weg wäre, die Ausgabe durch eine Art Stream-Editor zu leiten.

Folgendes funktioniert nicht

perl -e 'use Term::ANSIColor; print color "white"; print "ABC\n"; print color "reset";' | perl -pe 's/\^\[\[37m//g' | perl -pe 's/\^\[\[0m//g'

Keine Antwort auf die Frage, aber Sie können die Ausgabe auch weiterleiten moreoder less -Rdie Escape-Codes als Farbe anstelle eines Texteditors interpretieren.
Terdon

Antworten:


98

Die Zeichen ^[[37mund ^[[0msind Teil der ANSI-Escape-Sequenzen (CSI-Codes) . Siehe auch diese Spezifikationen .

GNU verwenden sed

sed 's/\x1b\[[0-9;]*m//g'
  • \x1b(oder \x1B) ist das Escape- Sonderzeichen
    ( sedunterstützt keine Alternativen \eund \033)
  • \[ ist das zweite Zeichen der Escape-Sequenz
  • [0-9;]* ist der Farbwert (die Farbwerte) für Regex
  • m ist das letzte Zeichen der Escape-Sequenz

⚠ Unter macOS unterstützt der Standardbefehl sedkeine Sonderzeichen, wie in den Kommentaren \evon slm und steamer25 angegeben . Verwenden Sie stattdessen, gseddass Sie mit installieren können brew install gnu-sed.

Beispiel mit der Befehlszeile von OP:   (OP bedeutet Original Poster)

perl -e 'use Term::ANSIColor; print color "white"; print "ABC\n"; print color "reset";' | 
      sed 's/\x1b\[[0-9;]*m//g'

Tom Hale schlägt vor, alle anderen Escape-Sequenzen zu entfernen, [a-zA-Z]anstatt nur den Buchstaben mzu verwenden, der für die Escape-Sequenz des Grafikmodus (Farbe) spezifisch ist. Aber [a-zA-Z]kann zu breit sein und könnte zu viel entfernen. Michał Faleński und Miguel Mota schlagen vor, nur einige Escape-Sequenzen mit [mGKH]und zu entfernen [mGKF]. Britton Kerin weist Kdarauf hin, dass zusätzlich zum mEntfernen der Farben aus gccFehler / Warnung auch verwendet werden muss (nicht vergessen, umzuleiten gcc 2>&1 | sed...).

sed 's/\x1b\[[0-9;]*m//g'           # Remove color sequences only
sed 's/\x1b\[[0-9;]*[a-zA-Z]//g'    # Remove all escape sequences
sed 's/\x1b\[[0-9;]*[mGKH]//g'      # Remove color and move sequences
sed 's/\x1b\[[0-9;]*[mGKF]//g'      # Remove color and move sequences
Last escape
sequence
character   Purpose
---------   -------------------------------
m           Graphics Rendition Mode (including Color)
G           Horizontal cursor move
K           Horizontal deletion
H           New cursor position
F           Move cursor to previous n lines

Verwenden perl

Die sedauf einigen Betriebssystemen installierte Version ist möglicherweise eingeschränkt (z. B. macOS). Der Befehl perlhat den Vorteil, dass er auf mehr Betriebssystemen im Allgemeinen einfacher zu installieren / aktualisieren ist. Adam Katz schlägt vor, \e(dasselbe wie \x1b) in PCRE zu verwenden .

Wählen Sie Ihren regulären Ausdruck abhängig davon, wie viele Befehle Sie filtern möchten:

perl -pe 's/\e\[[0-9;]*m//g'          # Remove colors only
perl -pe 's/\e\[[0-9;]*[mG]//g'
perl -pe 's/\e\[[0-9;]*[mGKH]//g'
perl -pe 's/\e\[[0-9;]*[a-zA-Z]//g'
perl -pe 's/\e\[[0-9;]*m(?:\e\[K)?//g' # Adam Katz's trick

Beispiel mit der Kommandozeile von OP:

perl -e 'use Term::ANSIColor; print color "white"; print "ABC\n"; print color "reset";' \
      | perl -pe 's/\e\[[0-9;]*m//g'

Verwendungszweck

Wie in Stuart Cardalls Kommentar erwähnt, wird diese sedBefehlszeile vom Projekt Ultimate Nginx Bad Bot (1000 Sterne) verwendet, um den E-Mail-Bericht zu bereinigen ;-)


2
Danke für den sedBefehl und die Erklärung. :)
Redsandro

2
Einige Farbcodes (zB Linux - Terminal) enthalten einen Präfix, zum Beispiel 1;31mso besser hinzufügen , ;um Ihre regex: cat colored.log | sed -r 's/\x1b\[[0-9;]*m//g'oder sie werden nicht abgezogen werden.
Redsandro

1
Das ist großartig, wenn es in github.com/mitchellkrogza/nginx-ultimate-bad-bot-blocker/blob/… verwendet wird , um den E-Mail-Bericht zu bereinigen.
Stuart Cardall

2
Beachten Sie, dass die OSX-Version von sedmit dem gezeigten Beispiel nicht funktioniert hat, die gsedVersion jedoch.
Slm

2
Mehr Kontext für den Kommentar von slm zu OSX sed: Steuerzeichen wie \ x1b werden nicht unterstützt. ZB stackoverflow.com/a/14881851/93345 . Den Befehl gsed erhalten Sie über brew install gnu-sed.
steamer25


10

Was angezeigt wird, ^[ist nicht ^ und [; Es ist das ASCII- ESCZeichen, das von Escoder erzeugt wird Ctrl[(die ^Notation bedeutet die Strg-Taste).

ESCist 0x1B hexadezimal oder 033 oktal, daher müssen Sie \x1Boder \033in Ihren Regexes verwenden:

perl -pe 's/\033\[37m//g; s/\033[0m//g'

perl -pe 's/\033\[\d*(;\d*)*m//g'

6

Wenn Sie etwas Einfaches bevorzugen, können Sie das Modul strip-ansi verwenden ( Node.js erforderlich):

$ npm install --global strip-ansi-cli

Dann benutze es so:

$ strip-ansi < colors.o

Oder geben Sie einfach eine Zeichenfolge ein:

$ strip-ansi '^[[37mABC^[[0m'

Dies ist eine nutzlose Verwendung von cat( UUOC ) - es sollte möglich sein, strip-ansi colors.ooder zumindest strip-ansi < colors.o.
Scott

1
@Scott Sicher, das können Sie auch strip-ansi < colors.o, aber aus Erfahrung kennen sich die Leute mit Rohrleitungen besser aus. Ich habe die Antwort aktualisiert.
Sindre Sorhus

gute einfache Lösung
Penghe Geng


2

Die "beantwortete" Frage hat bei mir nicht funktioniert, deshalb habe ich diesen regulären Ausdruck erstellt, um die vom perl Term :: ANSIColor-Modul erzeugten Escape-Sequenzen zu entfernen.

cat colors.o | perl -pe 's/\x1b\[[^m]+m//g;

Grawitys regulärer Ausdruck sollte gut funktionieren, aber die Verwendung von + scheint auch in Ordnung zu sein.


4
(1) Was meinst du damit The "answered" question? Meinen Sie die akzeptierte Antwort? (2) Dieser Befehl funktioniert nicht - er wird nicht einmal ausgeführt - weil er ein nicht übereinstimmendes (unsymmetrisches) Zitat enthält. (3) Dies ist eine nutzlose Verwendung von cat( UUOC ) - es sollte möglich sein, dies zu tun . (4) Wer hat jemals etwas über die Codes in einer Datei gesagt ? perl -pe command colors.o.o
Scott

2

Ich glaube, dies ist eine autorisierende Entfernung aller ANSI-Escape-Sequenzen :

perl -pe '
  s/\e\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]//g;
  s/\e[PX^_].*?\e\\//g;
  s/\e\][^\a]*(?:\a|\e\\)//g;
  s/\e[\[\]A-Z\\^_@]//g;'

(Bitte beachten Sie, dass Perl, wie viele andere Sprachen (aber nicht sed), übernimmt \eals Escape - Zeichen Esc, \x1boder \033durch Code, gezeigt in Terminals wie ^[. Ich verwende es hier , weil es noch intuitiver zu sein scheint.)

Dieser Perl-Befehl, den Sie bei Bedarf alle in einer Zeile ausführen können, enthält vier Ersetzungen:

Die erste geht nach CSI-Sequenzen (Escape-Code-Sequenzen, die mit dem "Control Sequence Introducer" von beginnen Esc[, der viel mehr abdeckt als die Select Graphic Rendition-Sequenzen , aus denen die Farbcodes und andere Textdekorationen bestehen).

Die zweite Ersetzung entfernt die verbleibenden Sequenzen, die nachfolgende Zeichen enthalten, und endet mit ST (dem String-Terminator Esc\). Der dritte Ersatz ist das Gleiche, aber ermöglicht auch Betriebssystem - Befehlssequenzen mit einem bis Ende BEL ( \x07, \007, oft \a).

Der vierte Ersatz entfernt die verbleibenden Fluchten.

Ziehen Sie auch in Betracht, andere ASCII-Zeichen mit der Breite Null wie BEL und andere undurchsichtige C0- und C1-Steuerzeichen zu entfernen . Ich habe benutzt s/[\x00-\x1f\x7f-\x9f\xad]+//g, was auch Delete und Soft Hyphen beinhaltet . Dies schließt Unicodes höher codierte Nullbreitenzeichen aus, aber ich glaube, dass es für ASCII (Unicode \x00- \xff) erschöpfend ist . Wenn Sie dies tun, entfernen Sie diese zuletzt, da sie an längeren Sequenzen beteiligt sein können.


1

"tput sgr0" hat dieses Steuerzeichen verlassen ^ (B ^ [
Hier ist eine modifizierte Version, um das zu erledigen .

perl -pe 's/\e[\[\(][0-9;]*[mGKFB]//g' logfile.log

Danke dafür ... das hat bei mir geklappt, um das loszuwerden, tput sgr0was die anderen Lösungen anscheinend nie loswerden können.
TxAG98,

0

Ich hatte ein ähnliches Problem mit dem Entfernen von Zeichen, die beim Sammeln interaktiver Top-Ausgaben über Putty hinzugefügt wurden, und dies half:

cat putty1.log | perl -pe 's/\x1b.*?[mGKH]//g'

3
Dies ist eine nutzlose Verwendung von cat( UUOC ) - es sollte möglich sein, dies zu tun . perl -pe command putty1.log
Scott

0

Das hat bei mir funktioniert (getestet unter Mac OS X)

perl -pe 's/\[[0-9;]*[mGKF]//g'
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.