使用tee命令输出时保留颜色

27

我试图使用tee获取一个有颜色的程序输出,并将其输出。我希望终端(stdout)上的输出具有颜色,但输出文件则没有。这是否可行?


@anishsane:对于不同的颜色生成方式(如回显ANSI代码、grep、ls等),答案会有所不同。 - choroba
据我所知,grep、ls等在终端上使用ANSI颜色代码。 - anishsane
5
这个问题必须有一个答案,因此它是一个真正的问题。 - cardiff space man
6
为什么人们认为这不是一个真正的问题?这个链接就是答案:http://superuser.com/a/751809/163119。 - Kokizzu
使用“expect”软件包中的“unbuffer”。在Ubuntu中,我只需使用sudo apt-get install expect-dev安装该软件包。问题解锁后,我会尽快发布关于此的答案。请参见https://dev59.com/BFTTa4cB1Zd3GeqPtYxB。 - Mihai Danila
显示剩余5条评论
2个回答

6
一种可能的方法是将转义字符打印到stderr,将主要内容打印到stdout。我已经在其中一个脚本中完成了这个操作,但这当然不是可扩展的选项。
编写一个专门的脚本来解析stdin,在stderr上放置转义序列,其他内容则放在stdout上,会是一个有趣的练习。:-)
然后 ./myScript.sh | filter_escapes | tee outfile.log
我没有看到任何可以实现这一点的脚本,但如果还没有可用的脚本,编写一个脚本应该很有趣。
至于你的问题,我认为以下内容应该足够:
ls --color=always | sed -r 'w /dev/stderr' | sed -r 's/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g' > /tmp/test

ls --color=always 替换为 ./your_script &,将 /tmp/test 替换为您想要的输出文件名。

其他实现方式:

ls --color=always | tee >(sed -r 's/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g' > /tmp/abcd)

注意:tee >(sed .... > logfile)语法
注意:
  1. 正则表达式借鉴自sampson-chen的回答。
  2. 在sed中使用w命令将/dev/stderr输出到日志文件是GNU sed的附加功能。

当您给出负面评价时,请留下评论... - anishsane
嗯...我不记得给它点踩了。抱歉。也许那天我心情不好。现在似乎无法取消它。 - nroose
没事了...我以为解决方案有误或者我在建议不良的编码实践。所以,当有人对一个问题/答案进行投票否定时,需要留下评论,以便改进。 - anishsane

1

是的,这是可能的。通过 sed 将您想要进入输出文件的结果传输,以删除用于格式化颜色的转义字符:

在 Linux 上:

sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g" 

在OS X上,因为它不是GNU sed:

sed -E "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g" 

我最近编写的工具的一部分正好可以实现你所描述的使用tee的功能:

https://github.com/sampson-chen/sack/blob/master/sack

 ack --color $sack__flags $@ $sack__cwd | tee >$sack__dev_null >(display_shortcuts) >(process_shorcut_paths | remove_escaped_chars > $sack__shortcut_file)

函数remove_escaped_chars包含一个检查操作系统版本的步骤,然后应用如上所示的sed脚本。

(注1:tee会自动将输出的副本重定向到stdout,因此我使用了>$sack__dev_null来防止这种情况:因为我想要添加额外的信息到打印到stdout中的内容中,正如在函数display_shortcuts中定义的那样)

(注2:tee本身绝对不会在我使用它时删除颜色格式化:我的怀疑是其他工具在使用管道时的默认行为。)


感谢您的回复;目前,我得到的结果与您想的相反。我正在使用颜色打印,但是 tee 命令从标准输出和输出文件中都删除了它们。换句话说,我正在尝试做与您建议的相反的事情(输出文件看起来很好,但标准输出并不按照我想要的方式工作)。 - pap42
2
@pap42 你在脚本中使用了哪些工具来产生颜色格式?例如像 grep 这样的工具,当作为管道的一部分使用时,默认会关闭颜色格式(您可以通过使用 grep 查找某些内容,然后将其传输到另一个 grep 来测试此功能)。要通过管道保留颜色格式,您需要查看这些工具是否有一些选项来实现此目的(例如 grep--color=always 选项)。我自己使用 tee 时肯定不会删除颜色格式:我怀疑是其他工具在管道中的默认行为。 - sampson-chen
实际上,我正在使用tee直接输出带有颜色的内容。而传输到标准输出的内容则没有颜色... - pap42
https://dev59.com/BFTTa4cB1Zd3GeqPtYxB - Mihai Danila

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接