Pomocí příkazu "skript" mohu zaznamenat interaktivní relaci na příkazový řádek. To však zahrnuje všechny kontrolní znaky a barevné kódy. Řídicí znaky (jako backspace) mohu odstranit pomocí „col -b“, ale nemůžu najít jednoduchý způsob, jak odstranit barevné kódy.
Všimněte si, že chci používat příkazový řádek běžným způsobem, takže tam nechci barvy deaktivovat - chci je pouze odstranit z výstupu skriptu. Také vím, že si můžu hrát a zkusit najít regexp, který věci opraví, ale doufám, že existuje jednodušší (a spolehlivější - co když existuje kód, o kterém nevím, když vyvíjím regexp?) Řešení.
Chcete-li ukázat problém:
spl62 tmp: script Skript byl spuštěn, soubor je TypeScript spl62 lepl: ls add-license.sed build-example.sh commit-test Push-docs .sh add-licence.sh build.sh delete-license.sed setup.py asn build-test.sh delete-licence.sh src build-doc.sh clean doc-src test.ini spl62 lepl: exit Skript byl dokončen, soubor je TypeScript spl62 tmp: cat -v TypeScript Skript byl zahájen Čt 9. června 2011 09:47:27 AM CLT Spl62 lepl: ls ^ M ^ [[0m ^ [[00madd-license.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-license.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 Skript proveden Čt 09 Červen 2011 09:47:29 AM CLT Spl62 tmp: col -b <TypeScript Skript byl zahájen Čt 9. června 2011 09:47:27 AM CLT Spl62 lepl: ls 0m00madd-licence.sed0m 00; 32mbuild-example.sh0m 00mcommit-test0m 00; 32mpush-docs.sh0m 00; 32madd-license.sh0m 00; 32mbuild.sh0m 00metete-license.sed0m 00msetup .p0m 01; 34masn0m 00; 32mbuild-test.sh0m 00; 32mdelete-license.sh0m 01; 34msrc0m [.____] 00; 32mbuild-doc.sh0m 00; 32mclean0m 01; 34mdoc-src0m 00mtest.ini0m spl62 lepl: exit Skript vytvořen Čt 9. června 2011 09:47:29 CLT
Následující skript by měl odfiltrovat všechny řídicí sekvence ANSI/VT100/xterm pro (na základě ctlseqs ). Minimálně otestováno, nahlaste prosím všechny případy nedostatečné nebo nadměrné shody.
#!/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;
}
Známé problémy:
#!/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;
}
Aktualizace Gillesovy odpovědi, aby také odstranila návraty vozíku a vymazala předchozí znaky z backspace, což pro mě bylo důležité pro TypeScript generovaný na 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;
}
V tomto případě bych použil sed
.
dělat:
cat -v TypeScript | sed -e "s/\x1b\[.\{1,5\}m//g"
sed -e "s/search/nahradit/g" je standardní materiál. regex je vysvětleno níže:
\x1b
shoduje se s Escape, který předchází barevnému kódu \[
odpovídá první otevřené závorce .\{1,5\}
odpovídá 1 až 5 libovolného jediného znaku. Muset \
složené rovnátka, aby Shell zabránil jejich manglování. m
poslední znak v regexu - obvykle sleduje barevný kód. //
prázdný řetězec, který má nahradit vše. g
se shoduje vícekrát na řádek.
cat TypeScript | Perl -pe 's/\e([^\[\]]|\[.*?[a-zA-Z]|\].*?\a)//g' | col -b > TypeScript-processed
# The "sed -r" trick does not work on every Linux, I still dunno why:
DECOLORIZE='eval sed "s,${END}\[[0-9;]*[m|K],,g"'
=> jak používat:
<commands that type colored output> | ${DECOLORIZE}
testováno na: - AIX 5.x/6.1/7.1 - Linux Mandrake/Mandriva/SLES/Fedora - SunOS
Existuje ansi2txt
příkaz v colorized-logs
balíček na Ubuntu. Odstraňuje pěkně barevné kódy ANSI, ale nezabývá se věcmi, jako jsou ukazatele průběhu vytvořené emitováním ^H
nebo ^M
znaky pro přepsání textu na místě. col -b
se s nimi vypořádá , takže pro dosažení nejlepších výsledků můžete tyto dva kombinovat
cat TypeScript | ansi2txt | col -b
Problém jsem vyřešil spuštěním scriptreplay
na obrazovce a uložením vyrovnávací paměti scrollback do souboru.
Následující skript očekávání to provede za vás.
Byl testován na logfiles s až 250 000 řádky. V pracovním adresáři potřebujete skriptový skript, soubor nazvaný „čas“ s 10 000 000 krát řádek „1 10“ a skript. Jako argument příkazového řádku potřebuji název vašeho souboru skriptu, například ./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
Časový soubor může být vygenerován pomocí
for i in $(seq 1 10000000); do echo "1 10" >> time; done
Raději bych pomocí specializovaných nástrojů převedl výstup skriptu na prostý text, který je neustále podporován a dobře testován, přes vlastní regexp. Takže to pro mě udělalo práci:
$ cat TypeScript | ansi2txt | col -bp > TypeScript.txt.bp
$ cat -v TypeScript.txt.bp
příkaz skriptu zachycuje do souboru TypeScript ansi2txt - převádí kód ansi s úniky, jako jsou barevné kódy, backspace atd., na normální text, ale zjistil jsem, že pár útěků stále zbývá. col-bp - zcela je odstranil.
Testoval jsem to na nejnovější disko Ubuntu a funguje to.
Zjistil jsem, že právě pomocí cat
bylo vše, co jsem potřeboval k zobrazení výstupu script
v terminálu. To nepomůže při přesměrování výstupu do jiného souboru, ale na rozdíl od cat -v
, col -b
nebo textový editor.
Chcete-li vyloučit barvy nebo uložit výsledky do souboru, zkopírujte a vložte výstup z cat
do textového editoru nebo do jiného příkazu cat
, tj .:
cat > endResult << END
<paste_copied_text_here>
END
Tuto otázku našel při hledání řešení stejného problému. Trochu víc kopání a našel tento skript v Live Journal na tomto odkazu. Dokonale jsem pro mě pracoval. Je to také velmi dobrý zápis o tomto problému ao tom, jak řešení funguje. Rozhodně stojí za přečtení. 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//; }
Ačkoli dosud uvedená řešení fungují pěkně na odstranění kontrolních sekvencí, odstraní také formátovací kódy. Výsledkem je, že tabulky ve výstupu jsou seskupeny dohromady. Mým požadavkem bylo pouze umožnit prohlížení a vyhledávání v souborech protokolu relací shromážděných z terminálu. Nejlepší řešení pro mě bylo použití méně -r.
less -r session.log