将ANSI颜色的代码文本发送到3个输出:屏幕,文件和文件过滤ANSI代码

时间:2014-12-13 22:53:31

标签: shell colors ansi-escape

我的程序正在将字符颜色文本发送到某个日志文件:

echo -e "\\033[38;5;2m-->\\033[0m Starting program." | tee $LogFile -a

导致完美彩色的日志行,但我想同时创建另一个没有ANSI 代码的日志文件,因为我需要在Windows中浏览此日志(我知道有一些ANSI浏览器用于Windows,但我更喜欢使用Total Commander浏览日志文件,它没有合适的插件。

所以,我的日志行中需要三个输出:

  • 某些彩色--> Starting program.到屏幕
  • 使用ANSI 代码的日志文件的相同颜色--> Starting program.行。
  • 日志文件相同的未着色--> Starting program.(据说没有ANSI 代码,或者我认为是这样)。

由于tee命令解决了第1点和第2点,上面的行很好,但我不知道如何添加一些选项来保存到另一个文件但没有ANSI代码,至少没有< strong>复制整行。 也许在mkfifo的帮助下使用重定向器,文件描述符?

顺便说一句,我现在的解决方法是输出重复(有点尴尬):

echo -e "\\033[38;5;2m--> Starting program.\\033[0m" | tee $LogFile -a
echo "--> Starting program." >> $NotANSILogFile

2 个答案:

答案 0 :(得分:3)

要将ansi代码发送到日志文件ansi.log和屏幕,同时还将非ansi版本发送到名为nonansi.log的日志文件,请使用:

echo -e "\\033[38;5;2m-->\\033[0m Starting program." | tee -a ansi.log | tee /dev/tty | sed $'s/\E[^m]*m//g' >>nonansi.log

如何运作

  • tee -a ansi.log

    第一个tee命令将ansi编码的字符串追加到日志文件ansi.log

  • tee /dev/tty

    第二个tee命令将ansi编码的字符串发送到屏幕。 (/dev/tty是当前屏幕的文件名。)

  • sed $'s/\E[^m]*m//g' >>nonansi.log

    最后一个命令sed删除了ansi序列,结果附加到nonansi.log

    sed命令包含在bash $'...'字符串中,因此转义字符可以简单地表示为\E。此替换命令查找以escape \E开头,以m结尾的序列,并将其删除。最后的g告诉sed对该行的每个转义序列执行此替换,而不仅仅是第一个。

    如果你有GNU sed,另一种方法是使用GNU的\o符号代替:

    sed 's/\o033[^m]*m//g' >>nonansi.log
    

    如果您既没有GNU sed也没有bash,那么您需要查看sed或您的shell为Esc字符提供的设施。

隐藏shell函数中的细节

如果您需要创建多个日志条目,最简单的方法是创建一个shell函数logger,以保存所有混乱的细节:

logger() { echo -e "$*" | tee -a ansi.log | tee /dev/tty | sed $'s/\E[^m]*m//g' >>nonansi.log; }

定义此函数后,可以通过提供ansi编码的字符串作为参数来执行任何日志条目:

logger "\\033[38;5;2m-->\\033[0m Start."

答案 1 :(得分:2)

此方法有效(需要安装perl)才能将输出发送到屏幕(ANSI)和两个文件$LogFile(ANSI)和$LogFile.plain(不含ANSI):

echo -e "\\033[38;5;2m--> Starting program.\\033[0m" | tee >(perl -pe 's/\e\[?.*?[\@-~]//g'>>"$LogFile".plain) $LogFile -a 

详细信息:

  • tee命令将输出拆分为屏幕(stdout)和perl命令。
  • perl行过滤ANSI代码。
  • perl的输出被重定向到普通的非ANSI日志文件(使用LogFile.plain作为其文件名)。

仅将输出发送到文件(不是屏幕)(仅与经典>/dev/null相同)。

echo -e "\\033[38;5;2m--> Starting program.\\033[0m" | tee >(perl -pe 's/\e\[?.*?[\@-~]//g'>>"$LogFile".plain) $LogFile -a >/dev/null

注意:

  • 使用>>代替>,正如增量日志文件所期望的那样。
  • -a命令使用了tee,原因与上述相同。
  • 我更愿意使用sed代替perl,但到目前为止我找到的所有sed示例都不起作用。如果有人知道,请报告。