在 Perl 中使用 ANSI 转义码 —— \e、Term::ANSIColor(核心模块)、-t STDOUT
Perl 在双引号字符串中支持 `\e` 转义 —— 本站记录的所有可输出 ANSI 的语言中最顺手的 ESC 字面形式。`print "\e[31mred\e[0m\n"` 在 Perl 5.000(1994 年发布)之后的所有版本,以及 macOS、Linux、BSD、现代 Windows(Windows Terminal / Conhost 1709+)上均可工作。标准辅助选 **`Term::ANSIColor`**,自 5.6 起随解释器一起分发的核心模块 —— `color("bold red")` 返回转义字符串,`colored(["bold red"], "text")` 包裹文本并自动重置,`colorstrip("\e[31mred\e[0m")` 干净地去除 ANSI(一个常见长尾 SERP 目标)。能力门控使用 Perl 惯用的 `-t STDOUT` 文件测试(在 TTY 上返回真)、`IO::Interactive::Tiny::is_interactive`(可移植包装),以及跨语言通用的 `$ENV{NO_COLOR}` 开关。需要完整 TUI 时链接 **`Curses::UI`**(Perl 的 ncurses 绑定);要查 termcap/terminfo 数据库时用 **`Term::Cap`**。 Perl 仍是系统管理一行命令与日志处理流水线的标准胶水语言 —— 单是 `colorstrip` 一招就服务于「如何从日志文件中剥离 ANSI」这类落到 Stack Overflow Perl 一行命令的大量搜索需求。
推荐库
- Term::ANSIColor
自 Perl 5.6 起的核心模块 —— 随每一个 Perl 解释器一起分发,无需安装。`color("bold red")` 返回 SGR 转义;`colored(["bold red"], "text")` 包裹文本并自动重置;`colorstrip($s)` 移除字符串中的所有 ANSI(清洗日志的标准 Perl 一行命令)。支持 16、256、TrueColor;尊重 `$ENV{ANSI_COLORS_DISABLED}` 与 `$ENV{NO_COLOR}`。
- Term::Cap
Perl 核心模块,用于 termcap / terminfo 查询。`Tgetent()` 加载 `$ENV{TERM}` 对应的 cap 条目;`Tputs()` 输出命名能力(`cl`、`cm`、`vi`/`ve`、`so`/`se`)。当你需要针对当前终端类型的正确转义字符串、而非现代默认的 VT 字节时使用。
- IO::Interactive::Tiny
对标准 TTY 检测的小巧零依赖包装:`is_interactive($fh)`。当你想要一个在重定向、管道、`IO::Scalar` 以及 `-t` 无法覆盖的各种「这是不是真正终端」边缘情况下都可移植的答案时使用,比裸 `-t STDOUT` 更稳。
- Curses::UI
构建于 `Curses`(ncurses 绑定)之上的 Perl 高层 TUI 框架 —— 窗口、对话框、菜单、列表框、文本编辑器、密码输入。当 `Term::ANSIColor` 不够用、需要完整面板式 UI 时的合适选择。
常用写法
# Perl supports \e directly in double-quoted strings — the most
# ergonomic ESC literal of any language we document. Single-quoted
# strings do NOT expand \e (or any backslash escapes), so always use
# qq{...} or "..." when emitting ANSI bytes.
use strict;
use warnings;
print "\e[1;31merror:\e[0m permission denied\n";
print "\e[33mwarn:\e[0m deprecated flag\n";
print "\e[32mok:\e[0m 142 tests passed\n";
# Truecolor — 38;2;R;G;B
print "\e[38;2;255;128;0morange truecolor\e[0m\n";use strict;
use warnings;
use Term::ANSIColor qw(color colored colorstrip);
# color() returns the SGR escape string — handcraft your own format:
print color("bold red"), "error:", color("reset"), " permission denied\n";
# colored() wraps text with the open + reset escape — cleaner:
print colored(["bold red"], "error:"), " permission denied\n";
print colored(["yellow"], "warn:"), " deprecated flag\n";
print colored(["green"], "ok:"), " 142 tests passed\n";
# 256-colour and truecolor via named SGR strings:
print colored(["rgb255"], "256-colour red"), "\n";
print colored(["r255g128b0"], "truecolor orange"), "\n";
# colorstrip — remove all ANSI from a string (canonical log scrubber):
my $dirty = "\e[31mERROR\e[0m at line 42";
print colorstrip($dirty), "\n"; # → "ERROR at line 42"use strict;
use warnings;
use Term::ANSIColor;
sub ansi_capable {
# Honour the Unix-standard kill switch first.
return 0 if $ENV{NO_COLOR};
# Term::ANSIColor's own switch — useful inside Term::ANSIColor wrappers.
return 0 if $ENV{ANSI_COLORS_DISABLED};
# Perl's idiomatic TTY check — true when filehandle is on a terminal.
return 0 unless -t STDOUT;
return 1;
}
sub style {
my ($text, $sgr) = @_;
return ansi_capable() ? "\e[${sgr}m${text}\e[0m" : $text;
}
print style("OK", "32"), "\n";
print style("FAIL", "1;31"), "\n";# Perl excels at sysadmin one-liners. These are the canonical
# scrubbers for ANSI in a log / CI output stream.
# Strip ALL ANSI escapes from a file using Term::ANSIColor's colorstrip:
perl -MTerm::ANSIColor=colorstrip -pe '$_ = colorstrip($_)' app.log
# Same with a hand-rolled regex (no module — useful in restricted envs):
perl -pe 's/\e\[[0-9;]*[A-Za-z]//g' app.log
# In-place edit — strip ANSI from many files at once, keep a .bak backup:
perl -i.bak -pe 's/\e\[[0-9;]*[A-Za-z]//g' *.log
# Colourise grep output — emit red+bold for matches, preserve context:
tail -F app.log | perl -MTerm::ANSIColor=colored \
-pe 's/(ERROR|FATAL)/colored([ "bold red" ], $1)/ge'