繁体   English   中英

如何从Perl终端管道而不会丢失颜色?

[英]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选项
  • 添加功能以支持在将其余选项传递给编译器之前删除的color-always命令行选项

您还可以使用expect脚本unbuffer来创建一个伪tty,如下所示:

unbuffer gcc file.c | cat

(其中cat是替代收件人)。

所有这些都基于从命令行使用colorgcc 应该有类比在Perl脚本中做类似的事情。

许多生成彩色输出的程序会检测它们是否正在写入TTY,如果不是则会关闭颜色。 这是因为当您只想捕获文本时,颜色代码很烦人,因此他们会尝试自动“做正确的事情”。

从类似程序中捕获颜色输出的最简单方法是告诉它写入颜色,即使它没有连接到TTY。 您必须阅读该程序的文档,以确定它是否具有该选项。

另一种选择是使用Pty而不是管道。 在Perl中,您可以使用IO :: Pty :: HalfDuplexIO :: 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM