You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

重定向程序输出时,转义序列为何会被自动移除?

问题

很多带命令行界面的Linux程序会使用不同的转义序列为文本上色,例如通过0x1B[31m序列将文本设为红色。我编写的Pascal程序在输出重定向到文件时,会保留这些转义序列;但像git status这类命令,输出重定向到文件后仅包含纯文本,无转义序列。

例如我的Pascal程序:

program ColorPrinting;
begin
    writeln(#27'[31m', 'Hello, world!', #27'[0m')
end.

将其输出重定向后,文件中确实包含转义序列:

$ ./test | hexdump -C
00000000  1b 5b 33 31 6d 48 65 6c  6c 6f 2c 20 77 6f 72 6c  |.[31mHello, worl|
00000010  64 21 1b 5b 30 6d 0a                              |d!.[0m.|
00000017

但对Git程序(已暂存内容显示为绿色,未暂存为红色)执行相同操作时,输出为纯文本:

$ git status -s > git-status.out && hexdump -C git-status.out
00000000  41 20 20 2e 67 69 74 69  67 6e 6f 72 65 0a 3f 3f  |A  .gitignore.??|
00000010  20 67 69 74 2d 73 74 61  74 75 73 2e 6f 75 74 0a  | git-status.out.|
00000020  3f 3f 20 74 65 73 74 2e  6f 75 74 0a 3f 3f 20 74  |?? test.out.?? t|
00000030  65 73 74 2e 70 61 73 0a                           |est.pas.|
00000038

我原本以为程序本身并不知晓输出的去向,重定向由Bash Shell完成,那么这种差异是如何实现的?是Bash自动清理部分程序输出流中的转义序列,还是另有原因?

解答

这种差异和Bash没有关系,核心原因是程序自身会主动判断输出目标是否为终端,进而决定是否输出颜色转义序列。

在Linux系统中,程序可以通过isatty()系统调用检测标准输出(stdout)是否连接到终端设备:

  • 如果检测到输出目标是终端,就输出带颜色的转义序列,让终端渲染出彩色文本;
  • 如果输出被重定向到文件、管道或者其他非终端设备,就自动关闭颜色输出,只输出纯文本。

你的Pascal程序属于“硬编码”输出转义序列,不管输出到哪里都会直接写入这些序列,所以重定向到文件后依然会保留。而Git这类成熟的命令行工具做了终端检测逻辑:

  • 默认情况下,只有当stdout是终端时才开启颜色输出;
  • 若要强制Git输出颜色(哪怕重定向到文件),可以使用git status -s --color=always参数,这样转义序列会被保留到输出文件中。

内容的提问来源于stack exchange,提问作者username

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 00:07:02