Eliminar códigos de color ANSI de la secuencia de texto

73

Examinando la salida de

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

en un editor de texto (p. ej. vi) muestra lo siguiente:

^[[37mABC
^[[0m

¿Cómo se eliminarían los códigos de color ANSI del archivo de salida? Supongo que la mejor manera sería canalizar la salida a través de un tipo de editor de flujo.

Lo siguiente no funciona

perl -e 'use Term::ANSIColor; print color "white"; print "ABC\n"; print color "reset";' | perl -pe 's/\^\[\[37m//g' | perl -pe 's/\^\[\[0m//g'
user001
fuente
No es una respuesta a la pregunta, pero también puede canalizar la salida moreo less -Rinterpretar los códigos de escape como color en lugar de un editor de texto.
terdon

Respuestas:

98

Los caracteres ^[[37my ^[[0mson parte de las secuencias de escape ANSI (códigos CSI) . Ver también estas especificaciones .

Usando GNU sed

sed 's/\x1b\[[0-9;]*m//g'
  • \x1b(o \x1B) es el carácter especial de escape
    ( sedno admite alternativas \ey \033)
  • \[ es el segundo personaje de la secuencia de escape
  • [0-9;]* son los valores de color regex
  • m es el último personaje de la secuencia de escape

Mac En macOS, el sedcomando predeterminado no admite caracteres especiales \ecomo los señalados por slm y steamer25 en los comentarios. Use en su lugar gsedque puede instalar usando brew install gnu-sed.

Ejemplo con la línea de comando de OP :   (OP significa Cartel original)

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

Tom Hale sugiere eliminar todas las demás secuencias de escape utilizando en [a-zA-Z]lugar de solo la letra mespecífica de la secuencia de escape del modo de gráficos (color). Pero [a-zA-Z]puede ser demasiado ancho y podría eliminar demasiado. Michał Faleński y Miguel Mota proponen eliminar solo algunas secuencias de escape usando [mGKH]y [mGKF]respectivamente. Britton Kerin indica Kque también se debe usar además de meliminar los colores del gccerror / advertencia (no se olvide de redirigir 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

Utilizando perl

La versión de sedinstalado en algunos sistemas operativos puede ser limitada (por ejemplo, macOS). El comando perltiene la ventaja de ser generalmente más fácil de instalar / actualizar en más sistemas operativos. Adam Katz sugiere usar \e(igual que \x1b) en PCRE .

Elija su expresión regular en función de la cantidad de comandos que desea filtrar:

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

Ejemplo con la línea de comando de OP:

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

Uso

Como lo señaló el comentario de Stuart Cardall , esta sedlínea de comando es utilizada por el proyecto Ultimate Nginx Bad Bot (1000 estrellas) para limpiar el informe del correo electrónico ;-)

olibre
fuente
2
Gracias por el sedcomando y la explicación. :)
Redsandro
2
Algunos códigos de color (p. Ej., Terminal de Linux) contienen un prefijo, p. Ej., Es 1;31mmejor agregarlo ;a su expresión regular: cat colored.log | sed -r 's/\x1b\[[0-9;]*m//g'o no se eliminarán.
Redsandro
1
esto es genial, lo usé en github.com/mitchellkrogza/nginx-ultimate-bad-bot-blocker/blob/… para limpiar el informe de correo electrónico.
Stuart Cardall
2
Tenga en cuenta que la versión OSX de sedno funcionó con el ejemplo que se muestra, pero la gsedversión sí funciona.
slm
2
Más contexto para el comentario de slm sobre OSX sed: no admite caracteres de control como \ x1b. Por ejemplo, stackoverflow.com/a/14881851/93345 . Puede obtener el comando gsed a través de brew install gnu-sed.
steamer25
21

He encontrado un mejor eliminador de secuencia de escape. Mira esto:

perl -pe 's/\x1b\[[0-9;]*[mG]//g'

usuario204331
fuente
2
¿Cuál es la mejora de la respuesta aceptada ( superuser.com/a/380778/46794 )?
Blaisorblade
44
@ Blaisorblade Funciona en OS X, mientras sed -rque NO.
BVengerov
10

Lo que se muestra como no^[ es y ; es el carácter ASCII , producido por o (la notación significa la tecla Ctrl). ^[ESCEscCtrl[^

ESCes 0x1B hexadecimal u 033 octal, por lo que debe usar \x1Bo \033en sus expresiones regulares:

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

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

Si prefiere algo simple, puede usar el módulo strip-ansi (se requiere Node.js ):

$ npm install --global strip-ansi-cli

Entonces úsalo así:

$ strip-ansi < colors.o

O simplemente pasar una cadena:

$ strip-ansi '^[[37mABC^[[0m'
Sindre Sorhus
fuente
Este es un uso inútil de cat( UUOC ): debería ser posible hacerlo strip-ansi colors.oo al menos strip-ansi < colors.o.
Scott
1
@Scott Claro, también puedes hacerlo strip-ansi < colors.o, pero por experiencia la gente está más familiarizada con las tuberías. He actualizado la respuesta.
Sindre Sorhus
buena solución simple
Penghe Geng
3

commandlinefu da esta respuesta que elimina los colores ANSI y los comandos de movimiento:

sed "s,\x1B\[[0-9;]*[a-zA-Z],,g"

Por solo colores, quieres:

 sed "s,\x1B\[[0-9;]*m,,g"
Tom Hale
fuente
3

Creo que esta es una eliminación autorizada de todas las secuencias de escape ANSI :

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

(Tenga en cuenta que perl, como muchos otros idiomas (pero no sed), acepta \ecomo carácter de escape Esc, \x1bo \033por código, que se muestra en las terminales como ^[. Lo estoy usando aquí porque parece más intuitivo).

Este comando perl, que puede ejecutar todo en una línea si lo prefiere, tiene cuatro reemplazos:

El primero va después de las secuencias CSI (secuencias de código de escape que comienzan con el "Introductor de secuencia de control" de Esc[, que cubre mucho más que las secuencias Seleccionar representación gráfica que componen los códigos de color y otras decoraciones de texto).

El segundo reemplazo elimina las secuencias restantes que involucran caracteres finales y terminan con ST (String Terminator, Esc\). El tercero de reemplazo es lo mismo, pero también permite comando del sistema operativo secuencias de terminar con una BEL ( \x07, \007, a menudo \a).

El cuarto reemplazo elimina los escapes restantes.

También considere eliminar otros caracteres ASCII de ancho cero, como BEL y otros caracteres de control C0 y C1 más oscuros . He estado usando s/[\x00-\x1f\x7f-\x9f\xad]+//g, que también incluye Delete y Soft Hyphen . Esto excluye los caracteres de ancho cero codificados más altos de Unicode, pero creo que es exhaustivo para ASCII (Unicode \x00- \xff). Si hace esto, elimine estos últimos ya que pueden estar involucrados en secuencias más largas.

Adam Katz
fuente
2

La pregunta "respondida" no funcionó para mí, así que creé esta expresión regular para eliminar las secuencias de escape producidas por el módulo Perl Term :: ANSIColor.

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

La expresión regular de Grawity debería funcionar bien, pero el uso de + también parece funcionar bien.

castl3bravo
fuente
44
(1) ¿Qué quieres decir con The "answered" question? ¿Te refieres a la respuesta aceptada? (2) Este comando no funciona, ni siquiera se ejecuta, porque tiene una cita sin igual (desequilibrada). (3) Este es un uso inútil de cat( UUOC ): debería ser posible hacerlo . (4) ¿Quién dijo algo sobre los códigos que están en un archivo? perl -pe command colors.o.o
Scott
1

"tput sgr0" dejó este carácter de control ^ (B ^ [
Aquí hay una versión modificada para encargarse de eso.

perl -pe 's/\e[\[\(][0-9;]*[mGKFB]//g' logfile.log
GustafAnkarloo
fuente
Gracias por esto ... Esto funcionó para que me deshaga de ese tput sgr0que las otras soluciones no parecen ser capaces de deshacerse de él.
TxAG98
0

Tuve un problema similar con la eliminación de caracteres agregados de la recopilación de salida superior interactiva a través de masilla y esto ayudó:

cat putty1.log | perl -pe 's/\x1b.*?[mGKH]//g'
Michał Faleński
fuente
3
Este es un uso inútil de cat( UUOC ): debería ser posible hacerlo . perl -pe command putty1.log
Scott
0

Esto es lo que funcionó para mí (probado en Mac OS X)

perl -pe 's/\[[0-9;]*[mGKF]//g'
Miguel Mota
fuente