有没有办法在 PowerShell 命令输出中保留 ANSI 控制代码?

Is there a way to preserve ANSI control codes in PowerShell command output?

在 PowerShell 中,有没有办法在将程序的输出分配给变量时保留用于将颜色信息传送到控制台的 ANSI 控制代码?

例如,我使用 Test Kitchen,它为 运行 的每个测试套件提供唯一的彩色输出。当我 运行 kitchen create INSTANCE 时,我得到几种颜色的输出。但是,如果我将输出分配给一个变量,或将其通过管道传递给另一个 cmdlet,例如 Tee-Object,那么颜色信息就会丢失。当结果沿着管道发送或分配给变量时,PowerShell 似乎会删除此信息:

kitchen create INSTANCE           # Colored output

$output = kitchen create INSTANCE
Write-Host $output                # Color information is lost

奇怪的是,我可以在自己的字符串中实现控制代码,并且当启用虚拟终端时 PowerShell 能够遵守它们。与命令输出不同,这些在变量赋值后仍然存在:

$output = "`u{001b}[31mHello"
Write-Host $output                # Results in colored output

因此,颜色信息似乎仅从程序的输出中被剥离,并且仅当值被分配或沿管道发送时。有没有办法从外部命令中保留这些控制代码?

and in the question comments, the problem does not lie within PowerShell. To quote 所述:

PowerShell is not to blame here. Most utilities (external programs) that are capable of colored output via ANSI escape sequences at least by default apply coloring selectively, namely only when stdout is connected to a terminal (i.e. when printing to the display). Such utilities may offer opt-in mechanisms to apply coloring unconditionally, via command-line options and/or environment variables.

添加到

  • 关于 Windows 我不知道有任何简单的解决方案,尽管也许有一种编程方式可以完成 script 实用程序在 Unix-like 平台上执行(见下文)。

  • Unix-like 平台 上,您可以使用 script 实用程序让外部程序相信它们已连接到终端,并且从而使它们产生彩色输出,否则它们会被抑制:

    • script 不是 POSIX-mandated 实用程序,但它至少附带一些 Linux 发行版,特别是 Ubuntu,以及 macOS。
    • 值得注意的是,macOS 和 Linux 实现使用不同的语法,如下所示。

示例:

  • 注:

    • ls --color=auto 用作现成的测试命令,因为它表现出 条件 着色行为。

    • ls --color=always 会表现出 无条件 着色行为,因此会避免对 script 的需要 - 因此,ls 确实 允许您请求无条件着色的实用程序示例; ls --color=auto 仅作为实用程序的 stand-in,而没有。

    • 下面($out = ...)的变量赋值被包裹在(...)中,目的是为了传递被赋值的值,所以您会立即看到颜色已保留。

  • Linux

($out = script -qc 'ls --color=auto')
  • macOS:
($out = script -q /dev/stdout ls --color=auto)