[英]How can I pipe from terminal in Perl without losing color?
我正在尝试编写一个perl脚本,它接受colorgcc的输出(或任何其他将彩色文本打印到终端的脚本),添加/删除部分字符串,然后以与输入字符串相同的颜色打印结果。
以下代码将在color_producing_script生成的每一行前面打印“Hello World”。 输出将全部为黑色,而输入为多色。 如何修改此脚本以保留原始颜色?
open(CMD, "color_producing_script |");
while(<CMD>) {
print 'Hello World' . $_;
}
我正在使用bash终端。
编辑
根据优秀的第一条评论,这本身并不是Perl问题。 刚刚运行color_producing_script | cat
color_producing_script | cat
脱掉了颜色。 因此,问题可以改为“你如何通过管道强制颜色?”
编辑2
看起来最新版本的gcc(1.3.2)在if子句中包含了CGCC_FORCE_COLOR环境变量,如果已定义,colorgcc会强制颜色:
export CGCC_FORCE_COLOR=true
color_producing_script
在管道中使用时是否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
配置文件中的color-always选项 您还可以使用expect
脚本unbuffer
来创建一个伪tty,如下所示:
unbuffer gcc file.c | cat
(其中cat
是替代收件人)。
所有这些都基于从命令行使用colorgcc
。 应该有类比在Perl脚本中做类似的事情。
许多生成彩色输出的程序会检测它们是否正在写入TTY,如果不是则会关闭颜色。 这是因为当您只想捕获文本时,颜色代码很烦人,因此他们会尝试自动“做正确的事情”。
从类似程序中捕获颜色输出的最简单方法是告诉它写入颜色,即使它没有连接到TTY。 您必须阅读该程序的文档,以确定它是否具有该选项。
另一种选择是使用Pty而不是管道。 在Perl中,您可以使用IO :: Pty :: HalfDuplex或IO :: Pty :: Easy执行此操作 ,这两者都是低级模块IO :: Pty的高级包装器。
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:强制exec'd进程具有无缓冲的stdout
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.