web-dev-qa-db-fra.com

Suppression des caractères de contrôle (y compris les codes / couleurs de console) de la sortie du script

Je peux utiliser la commande "script" pour enregistrer une session interactive sur la ligne de commande. Cependant, cela inclut tous les caractères de contrôle et codes couleur. Je peux supprimer des caractères de contrôle (comme le retour arrière) avec "col -b", mais je ne peux pas trouver un moyen simple de supprimer les codes de couleur.

Notez que je veux utiliser la ligne de commande de la manière habituelle, donc je ne veux pas désactiver les couleurs - je veux juste les supprimer de la sortie du script. De plus, je sais que je peux jouer et essayer de trouver une expression rationnelle pour corriger les choses, mais j'espère qu'il existe une solution plus simple (et plus fiable - et s'il y a un code que je ne connais pas lorsque je développe la regexp?).

Pour montrer le problème:

 spl62 tmp: script 
 Script démarré, le fichier est TypeScript 
 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 clean doc-src test.ini 
 spl62 lepl: exit 
 Script terminé, le fichier est TypeScript 
 spl62 tmp: cat -v TypeScript 
 Script démarré le jeu 09 juin 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; 32madd-licence.sh ^ [[0m ^ [[00; 32mbuild.sh ^ [[0m ^ [[00mdelete-licence.sed ^ [[0m ^ [[00msetup.py ^ [[0m ^ M 
 ^ [[01; 34masn ^ [[0m ^ [[00; 32mbuild-test.sh ^ [[0m ^ [[00; 32mdelete-licence.sh ^ [[0m ^ [[01; 34msrc ^ [[0m ^ M 
 ^ [[00; 32mbuild-doc.sh ^ [[0m ^ [[00; 32mclean ^ [[0m ^ [[01; 34mdoc-src ^ [[0m ^ [[00mtest.ini ^ [[0m ^ M 
 Spl62 lepl: exit ^ M 
 
 Script réalisé le jeu 09 Juin 2011 09:47:29 CLT 
 Spl62 tmp: col -b <TypeScript 
 Script démarré le jeu 09 juin 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: exit 
 
 Script réalisé le jeu 09 juin 2011 09:47:29 AM CLT 
71
andrew cooke

Le script suivant doit filtrer toutes les séquences de contrôle ANSI/VT100/xterm pour (basé sur ctlseqs ). Testé de manière minimale, veuillez signaler tout sous-match ou sur-match.

#!/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;
}

Problèmes connus:

  • Ne se plaint pas de séquences mal formées. Ce n'est pas à ça que sert ce script.
  • Les arguments de chaîne multiligne vers DCS/PM/APC/OSC ne sont pas pris en charge.
  • Les octets compris entre 128 et 159 peuvent être analysés comme caractères de contrôle, bien que cela soit rarement utilisé. Voici une version qui analyse les caractères de contrôle non ASCII (cela modifie le texte non ASCII dans certains encodages, y compris UTF-8).
#!/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;
}

Mettre à jour la réponse de Gilles pour supprimer également les retours chariot et effacer le retour arrière des caractères précédents, qui étaient tous deux importants pour moi pour un TypeScript généré sur Cygwin:

#!/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;
}
31
dewtell

J'utiliserais sed dans ce cas.

faire:

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

sed -e "s/search/replace/g" est standard. l'expression régulière est expliquée ci-dessous:

\x1b correspond à l'Escape précédant le code couleur \[ correspond au premier support ouvert .\{1,5\} correspond à 1 à 5 de n'importe quel caractère. Devoir \ les accolades pour empêcher le coquillage de les mutiler. m dernier caractère dans l'expression régulière - suit généralement le code de couleur. // chaîne vide pour quoi remplacer tout. g correspond plusieurs fois par ligne.

12
Glorytoad
cat TypeScript | Perl -pe 's/\e([^\[\]]|\[.*?[a-zA-Z]|\].*?\a)//g' | col -b > TypeScript-processed
9
Peter Nore
# The "sed -r" trick does not work on every Linux, I still dunno why:
DECOLORIZE='eval sed "s,${END}\[[0-9;]*[m|K],,g"'

=> comment utiliser:

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

testé sur: - AIX 5.x/6.1/7.1 - Linux Mandrake/Mandriva/SLES/Fedora - SunOS

6
scavenger

Il y a un ansi2txt dans la commande colorized-logs package sur Ubuntu. Il supprime bien les codes de couleur ANSI, mais il ne traite pas des choses comme les barres de progression produites en émettant ^H ou ^M caractères pour remplacer le texte en place. col -b peut gérer ces , donc pour de meilleurs résultats, vous pouvez combiner les deux

cat TypeScript | ansi2txt | col -b
5
Marius Gedminas

J'ai résolu le problème en exécutant scriptreplay dans un écran et en vidant le tampon de défilement dans un fichier.

Le script d'attente suivant le fait pour vous.

Il a été testé pour les fichiers journaux avec jusqu'à 250 000 lignes. Dans le répertoire de travail, vous avez besoin de votre scriptlog, d'un fichier appelé "time" avec 10.000.000 fois la ligne "1 10" et du script. J'ai besoin du nom de votre fichier de script comme argument de ligne de commande, comme ./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

Le fichier horaire peut être généré par

for i in $(seq 1 10000000); do echo "1 10" >> time; done
3
hnkchnsk

Je préférerais utiliser des outils spécialisés pour convertir la sortie du script en texte brut, qui est constamment pris en charge et bien testé, plutôt que l'expression rationnelle personnalisée. Donc, cela a fonctionné pour moi:

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

la commande de script capture dans le fichier TypeScript ansi2txt - convertit le code ansi avec des échappements comme les codes de couleur, les espaces arrière, etc. en texte normal, mais j'ai trouvé que quelques échappements restaient. col -bp - les a supprimés complètement.

J'ai testé cela sur la dernière discothèque Ubuntu, et cela fonctionne.

1
Dmytro Brazhnyk

J'ai trouvé que l'utilisation de cat était tout ce dont j'avais besoin pour afficher la sortie de script dans le terminal. Cela n'aide pas lors de la redirection de la sortie vers un autre fichier, mais rend le résultat lisible, contrairement à cat -v, col -b, ou un éditeur de texte.

Pour éliminer les couleurs ou enregistrer les résultats dans un fichier, copiez et collez manuellement la sortie de cat dans un éditeur de texte ou dans une autre commande cat, à savoir:

cat > endResult << END
<paste_copied_text_here>
END
1
Roger Dueck

J'ai trouvé cette question en cherchant la solution au même problème. Un peu plus en creusant et j'ai trouvé ce script sur Live Journal à ce lien. J'ai travaillé parfaitement pour moi. C'est aussi une très bonne description de ce problème et du fonctionnement de la solution. Vaut vraiment le détour. 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//; }
1
SammerV

Bien que les solutions proposées jusqu'à présent fonctionnent bien pour supprimer les séquences de contrôle, elles suppriment également les codes de formatage. Le résultat est que les tables dans la sortie sont écrasées ensemble. Mon exigence était simplement de pouvoir visualiser et rechercher dans les fichiers journaux de session collectés à partir du terminal. La solution qui fonctionnait le mieux pour moi était d'utiliser moins -r.

less -r session.log
0
AliA