J'ai un script qui produit une sortie avec des couleurs et je dois supprimer les codes ANSI.
#!/bin/bash
exec > >(tee log) # redirect the output to a file but keep it on stdout
exec 2>&1
./somescript
La sortie est (dans le fichier journal):
Java (pid 12321) is running...@[60G[@[0;32m OK @[0;39m]
Je ne savais pas comment mettre le caractère ESC ici, alors j'ai mis @
à sa place.
J'ai changé le script en:
#!/bin/bash
exec > >(tee log) # redirect the output to a file but keep it on stdout
exec 2>&1
./somescript | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g"
Mais maintenant, il me donne (dans le fichier journal):
Java (pid 12321) is running...@[60G[ OK ]
Comment puis-je aussi supprimer ce '@[60G
?
Peut-être existe-t-il un moyen de désactiver complètement la coloration du script entier?
selon Wikipedia , le [m|K]
dans la commande sed
que vous utilisez est spécialement conçue pour gérer m
(la commande de couleur) et K
(la commande "effacer une partie de la ligne"). Votre script tente de définir la position absolue du curseur sur 60 (^[[60G
) pour obtenir tous les OK dans une ligne, ce que votre ligne sed
ne couvre pas.
(Correctement, [m|K]
devrait probablement être (m|K)
ou [mK]
, parce que vous n'essayez pas de faire correspondre un caractère de pipe. Mais ce n'est pas important pour le moment.)
Si vous passez cette dernière correspondance dans votre commande à [mGK]
ou (m|G|K)
, vous devriez pouvoir capturer cette séquence de contrôle supplémentaire.
./somescript | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g"
Je ne pouvais obtenir de résultats décents d'aucune des autres réponses, mais ce qui suit a fonctionné pour moi:
somescript | sed -r "s/[[:cntrl:]]\[[0-9]{1,3}m//g"
Si je ne retirais que le caractère de contrôle "^ [", il restait le reste des données de couleur, par exemple, "33m". Y compris le code de couleur et "m" a fait l'affaire. Je suis perplexe avec s/\ x1B // g ne fonctionne pas car\x1B [31m fonctionne certainement avec echo.
Pour Mac OSX ou BSD, utilisez
./somescript | sed $'s,\x1b\\[[0-9;]*[a-zA-Z],,g'
J'ai également eu le problème que parfois, le caractère SI est apparu.
C'est arrivé par exemple avec cette entrée: echo "$(tput setaf 1)foo$(tput sgr0) bar"
Voici un moyen de supprimer également le caractère SI (décalage) (0x0f)
./somescript | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g" | sed "s/\x0f//g"
Hmm, je ne sais pas si cela fonctionnera pour vous, mais 'tr' sera 'strip' (effacer) codes de contrôle - essayez:
./somescript | tr -d '[:cntrl:]'
IMHO, la plupart de ces réponses essaient trop de restreindre le contenu du code d'échappement. En conséquence, il leur manque des codes communs tels que [38;5;60m
(Couleur ANSI au premier plan 60 à partir du mode 256 couleurs).
Ils ont également besoin de l’option -r
Qui active extensions GN . Ce ne sont pas nécessaires; ils font juste la regex mieux lire.
Voici une réponse plus simple qui gère les échappements de 256 couleurs et fonctionne sur les systèmes avec non-GNU sed
:
./somescript | sed 's/\x1B\[[0-9;]\+[A-Za-z]//g'
Cela va attraper tout ce qui commence par [
, A un nombre quelconque de décimales et de points-virgules et se termine par une lettre. Cela devrait intercepter n'importe lequel des séquences d'échappement ANSI communes .
Pour les funsies, voici une solution plus large et plus générale (mais non testée) pour toutes les séquences d'échappement ANSI imaginables :
./somescript | sed 's/\x1B[@A–Z\\\]^_]|\x1B\[[0–9:;<=>?]*[-!"#$%&\'()*+,.\/]*[@A–Z[\\\]^_`a–z{|}~]//g'
(et si vous avez le problème SI de @ edi9999, ajoutez | sed "s/\x0f//g"
à la fin; cela fonctionne pour tout caractère de contrôle en remplaçant 0f
par l'hex du caractère non souhaité)
J'avais un problème similaire. Toutes les solutions que j'ai trouvées ont bien fonctionné pour les codes de couleur, mais n'ont pas supprimé les caractères ajoutés par "$(tput sgr0)"
(réinitialisation des attributs).
En prenant, par exemple, la solution dans le commentaire de davemyron , la longueur de la chaîne résultante dans l'exemple ci-dessous est 9, et non 6:
#!/usr/bin/env bash
string="$(tput setaf 9)foobar$(tput sgr0)"
string_sed="$( sed -r "s/\x1B\[[0-9;]*[JKmsu]//g" <<< "${string}" )"
echo ${#string_sed}
Afin de fonctionner correctement, la regex devait être étendue pour correspondre également à la séquence ajoutée par sgr0
("\E(B
"):
string_sed="$( sed -r "s/\x1B(\[[0-9;]*[JKmsu]|\(B)//g" <<< "${string}" )"
Fonction beaucoup plus simple dans Bash pur pour filtrer les codes ANSI courants d'un flux de texte:
# Strips common ANSI codes from a text stream
shopt -s extglob # Enable Bash Extended Globbing expressions
ansi_filter() {
local line
local IFS=
while read -r line || [[ "$line" ]]; do
echo "${line//$'\e'[\[(]*([0-9;])[@-n]/}"
done
}
Voir:
La solution de @ jeff-bowman m'a aidé à me débarrasser de CERTAINS codes de couleur. J'ai ajouté une autre petite portion à la regex afin d'en supprimer un peu plus:
sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g" # Original. Removed Red ([31;40m[1m[error][0m)
sed -r "s/\x1B\[([0-9];)?([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g" # With an addition, removed yellow and green ([1;33;40m[1m[warning][0m and [1;32;40m[1m[ok][0m)
^^^^^^^^^
remove Yellow and Green (and maybe more colors)
Si on a besoin de faire ceci dans un script Bash, la fonction suivante peut être utilisée:
# Strip escape codes/sequences [$1: input, $2: target variable]
function strip_escape_codes() {
local input="${1//\"/\\\"}" output="" i char within_code=0
for ((i=0; i < ${#input}; ++i)); do
char="${input:i:1}" # get current character
if (( ${within_code} == 1 )); then # if we're currently within an escape code, check if end of
case "${char}" in # code is reached, i.e. if current character is a letter
[a-zA-Z]) within_code=0 ;; # we're no longer within an escape code
esac
continue
fi
if [[ "${char}" == $'\e' ]]; then # if current character is '\e', we've reached an escape code
within_code=1 # now we're within an escape code
continue
fi
output+="${char}" # if none of the above applies, add current character to output
done
eval "$2=\"${output}\"" # assign output to target variable
}
Voici un exemple correspondant au cas d'utilisation de la question d'origine. Enregistrer sous example.sh
puis exécutez <command-producing-colored-output> | example.sh
:
#!/bin/bash
# copy&paste function strip_escape_codes here
while read -r line; do
strip_escape_codes "${line}" stripped
echo "${stripped}"
done