it-swarm.cn

从脚本输出中删除控制字符(包括控制台代码/颜色)

我可以使用“脚本”命令在命令行上记录交互式会话。但是,这包括所有控制字符and颜色代码。我可以使用“ col -b”删除控制字符(如退格键),但是找不到删除颜色代码的简单方法。

请注意,我想以常规方式使用命令行,因此不想在此处禁用颜色-我只想从脚本输出中删除它们。另外,我知道可以尝试并尝试找到一个正则表达式来解决问题,但是我希望有一个更简单(更可靠的方法-如果开发我的正则表达式时我不知道有什么代码怎么办?)解决方案。

要显示问题:

 spl62 tmp:脚本
脚本已启动,文件为TypeScript 
 spl62 lepl:ls 
 add-licence.sed build-example.sh提交测试Push-docs .sh 
 add-licence.sh build.sh删除许可证.sed setup.py 
 asn build-test.sh delete-licence.sh src 
 build-doc.sh clean doc-src test.ini 
 spl62 lepl:退出
脚本已完成,文件为TypeScript 
 spl62 tmp:cat -v TypeScript 
脚本于6月9日星期四开始2011 09:47:27 AM 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 on Thu 09 CLT 2011年6月09:47:29 CLT 
 spl62 tmp:col -b <TypeScript 
脚本开始于2011年6月9日星期四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 
 
脚本执行时间:2011年6月9日星期四,CLT 
71
andrew cooke

以下脚本应针对(基于 ctlseqs )过滤掉所有ANSI/VT100/xterm控制序列。经过最少测试,请报告任何不匹配或过度匹配。

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

已知的问题:

  • 不要抱怨格式错误的序列。这不是该脚本的目的。
  • 不支持DCS/PM/APC/OSC的多行字符串参数。
  • 尽管很少使用,但可以将128–159范围内的字节解析为控制字符。这是一个解析非ASCII控制字符的版本(它将以某些编码(包括UTF-8)处理非ASCII文本)。
#!/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;
}
58

更新Gilles的答案还可以删除回车符并对以前的字符进行退格擦除,这对我在Cygwin上生成的TypeScript来说都很重要:

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

在这种情况下,我将使用sed

做:

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

sed -e“ s/search/replace/g”是标准的东西。正则表达式解释如下:

\x1b匹配颜色代码前的转义符\[匹配第一个方括号.\{1,5\}匹配任何单个字符的1-5。必须\大括号以防止Shell破坏它们。 m正则表达式中的最后一个字符-通常尾随颜色代码。 //空字符串,用于替换所有内容。 g每行多次匹配它。

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

=>使用方法:

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

在以下设备上测试过:-AIX 5.x/6.1/7.1-Linux Mandrake/Mandriva/SLES/Fedora-SunOS

6
scavenger

在Ubuntu上的_ansi2txt_软件包中有一个 _colorized-logs_ 命令。它可以很好地删除ANSI颜色代码,但不能处理通过发出_^H_或_^M_字符覆盖原位文本而产生的进度条之类的事情。 _col -b_可以处理those,因此为了获得最佳结果,可以将两者结合使用

_cat TypeScript | ansi2txt | col -b
_
5
Marius Gedminas

我通过在屏幕中运行scriptreplay并将转回缓冲区转储到文件中来解决了这个问题。

下面的Expect脚本会为您执行此操作。

已针对最多250.000行的日志文件进行了测试。在工作目录中,您需要脚本脚本,一个名为“ time”的文件以及该脚本,该文件中包含行号“ 1 10”的10.000.000倍。我需要您的脚本文件的名称作为命令行参数,例如./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

时间文件可以通过以下方式生成

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

我宁愿使用专门的工具将脚本输出转换为纯文本,而自定义regexp经常支持该脚本并将其进行良好的测试。所以这对我有用:

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

脚本命令捕获到TypeScript文件ansi2txt中-将带有转义符(如颜色代码,退格键等)的ansi代码转换为常规文本,但是我发现夫妇转义符仍然保留。 col -bp-完全删除它们。

我已经在最新的Ubuntu迪斯科舞厅上对此进行了测试,并且可以正常工作。

1
Dmytro Brazhnyk

我发现只需要使用cat即可在终端中查看script的输出。当将输出重定向到另一个文件时,这没有帮助,但是确实使结果可读,而不像cat -vcol -b或文本编辑器。

要消除颜色或将结果保存到文件中,请手动将cat的输出复制并粘贴到文本编辑器中,或粘贴到另一个cat命令中,即:

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

寻找相同问题的解决方案时发现了这个问题。进行了一些进一步的挖掘,并在此链接的Live Journal中找到了此脚本。我为我完美地工作。关于此问题以及该解决方案的工作方式,这也是很好的文章。绝对值得一读。 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

尽管到目前为止给出的解决方案可以很好地删除控制序列,但是它们也可以删除格式化代码。结果是输出中的表被压缩在一起。我的要求只是能够查看和搜索从终端收集的会话日志文件。最适合我的解决方案是使用less -r。

less -r session.log
0
AliA