如何清理 stdout/stderr 颜色输出

如何清理 stdout/stderr 颜色输出

我有一个程序会输出如下内容:

^[0;33m"2015-02-09 11:42:36 +0700 114.125.x.x access"^[0m

是否有内置的 Linux 程序可以将输出清理成这样的内容

"2015-02-09 11:42:36 +0700 114.125.x.x access"

答案1

这些是 ANSI 控制序列。至少据我所知,没有任何内置程序可以删除这些代码。然而,一个简单的sed脚本就可以满足您的需求:

sed -r 's/\x1b_[^\x1b]*\x1b[\]//g; s/\x1B\[[^m]*m//g'

将上述内容与您的示例输入一起使用:

$ echo $'\e[0;33m"2015-02-09 11:42:36 +0700 114.125.x.x access"\e[0m'  | sed -r 's/\x1b_[^\x1b]*\x1b[\]//g; s/\x1B\[[^m]*m//g'                    
"2015-02-09 11:42:36 +0700 114.125.x.x access"

OSX 或其他 BSD 系统

对于 OSX (BSD) sed,命令不能用分号链接在一起。尝试一下:

sed -e 's/\x1b_[^\x1b]*\x1b[\]//g' -e 's/\x1B\[[^m]*m//g'

答案2

sed 脚本的想法是好的(并且有几个脚本可用于此目的),但建议的脚本可以改进:

  • 该块s/\x1b_[^\x1b]*\x1b[\]//g可能旨在过滤掉应用模式命令。然而,读者不太可能发现这些用过的,如 xterm 文档中所述:

APC ST
没有任何。 xterm不实现 APC 功能;被忽略。 不必是可打印字符。

  • 如果下划线改为右方括号],那么它将匹配一些操作系统控制。然而,这些在终端中的主要用途还是使用以\007(ASCII BEL) 结尾的变体作为 xterm 样式标题(通常在 bash/zsh 提示字符串中使用)。

考虑到这些因素,更好的第一个块可能是非贪婪匹配escape\ 或者 BEL。但sed会进行贪婪的匹配。与其变得复杂,不如

s/\x1b\][^\x07]*\x07//g

应该足够了。

另一个块也有问题。从一开始就太贪心了:

s/\x1B\[[^m]*m//g

因为它假设在删除应用程序模式(或操作系统)命令后,shell 输出中唯一剩余的转义序列将是那些更改视频模式的转义序列,即 SGR(以 结尾m)。稍作改变,表达式将仅过滤掉 SGR 序列,而不会失去理智并删除以 开头的所有内容escape[,例如,

s/\x1B\[[;0-9]*m//g

过滤掉颜色转义序列可以被视为将终端输出过滤为纯文本的特殊情况,如中所回答我可以使用 unix utils 以编程方式将 ANSI 控制代码“烧入”到文件中吗?在提出这个问题之前一周。

进一步阅读:

相关内容