我正在尝试编写一个perl脚本,它接受colorgcc的输出(或任何其他将彩色文本打印到终端的脚本),添加/删除部分字符串,然后将结果打印在相同的颜色作为输入字符串。
以下代码将在 color_producing_script 生成的每一行前面打印“Hello World”。输出将全部为黑色,而输入为多色。如何修改此脚本以保留原始颜色?
open(CMD, "color_producing_script |");
while(<CMD>) {
print 'Hello World' . $_;
}
我正在使用 bash 终端。
修改
根据优秀的第一条评论,这本身并不是Perl问题。只需运行color_producing_script | cat
即可剥离颜色。因此,问题可以改为“你如何通过管道强制颜色?”
修改2
看起来最新版本的gcc(1.3.2)在if子句中包含CGCC_FORCE_COLOR环境变量,如果已定义,则colorgcc强制颜色:
export CGCC_FORCE_COLOR=true
答案 0 :(得分:4)
color_producing_script
在管道中使用时会改变其行为吗?尝试
color_producing_script | cat
在命令行。它可能有一个强制颜色输出的选项,即使它是。
Perl脚本colorgcc
专门检查输出是否为非tty,如果是这种情况则跳过着色。
# Get the terminal type.
$terminal = $ENV{"TERM"} || "dumb";
# If it's in the list of terminal types not to color, or if
# we're writing to something that's not a tty, don't do color.
if (! -t STDOUT || $nocolor{$terminal})
{
exec $compiler, @ARGV
or die("Couldn't exec");
}
修改强>
您可以通过以下一种或多种方式修改脚本:
~/.colorgccrc
配置文件你也可以使用expect
脚本unbuffer
创建一个像这样的伪tty:
unbuffer gcc file.c | cat
(其中cat
是替代收件人)。
所有这些都基于命令行中的colorgcc
。在Perl脚本中应该有用于做类似事情的类比。
答案 1 :(得分:3)
许多生成彩色输出的程序会检测它们是否正在写入TTY,如果不是,则会关闭颜色。这是因为当您只想捕获文本时,颜色代码很烦人,因此他们会尝试自动“做正确的事情”。
从这样的程序中捕获颜色输出的最简单方法是告诉它写入颜色,即使它没有连接到TTY。您必须阅读该程序的文档,以确定它是否具有该选项。
另一种选择是使用Pty而不是管道。在Perl中,您可以使用IO::Pty::HalfDuplex或IO::Pty::Easy来执行此操作,这两个文件都是低级模块IO::Pty周围的高级包装器。
答案 2 :(得分:3)
ColorGCC的源代码非常清楚这个主题!
#! /usr/bin/perl -w
# ...
# from: colorgcc-4.1.2/colorgcc-4.1.2
# downloaded from: http://www.console-colors.de/index.php?n=ConsColors.Downloads
#
# Note:
#
# colorgcc will only emit color codes if:
#
# (1) Its STDOUT is a tty and
# (2) the value of $TERM is not listed in the "nocolor" option.
#
# If colorgcc colorizes the output, the compiler's STDERR will be
# combined with STDOUT. Otherwise, colorgcc just passes the output from
# the compiler through without modification.
# .....
# If it's in the list of terminal types not to color, or if
# we're writing to something that's not a tty, don't do color.
if (! -t STDOUT || $nocolor{$terminal})
{
exec $compiler, @ARGV
or die("Couldn't exec");
}
除了在Perl中使用Pty而不是管道(正如cjm已经指出的那样)之外,你可以欺骗应用程序认为它的stdin是交互式的,而不是命令行上的管道。
例如:
# Linux
script -c "[executable string]" /dev/null
# FreeBSD, Mac OS X
script -q /dev/null "[executable string]"
有关进一步的解决方案,请参阅:bash: force exec'd process to have unbuffered stdout