跳到主要内容
ansicode

在你的 shell 中使用 ANSI 转义码

五种 shell,五种把 ESC 字节送上 stdout 的语法 —— 并排呈现。Bash 与 Zsh 提供 ANSI-C 引用($'\e[…]')和 printf;Zsh 还增加了仅在 prompt 中生效的 %F{red} 快捷形式;Fish 完全不用转义字面量,而以 set_color 内建命令实现;PowerShell 7+ 内置 $PSStyle,但 5.1 仍需 [char]27;cmd.exe 依赖主机层的 ConPTY 支持,批处理本身没有干净的 ESC 写法。每个 shell 都附带可用片段、最常踩的那个坑,以及对应序列的链接。

Bash

在 Bash 中使用 ANSI 转义码

Bash 有三种可靠方式输出 ESC 字节:printf 配合八进制 / 十六进制转义(符合 POSIX,跨 dash / sh 最稳);ANSI-C 引用 $'\e[...]'(仅 bash + zsh,但可读性最佳);以及 tput(基于 terminfo,跨 $TERM 最稳)。请避免 echo -e —— 它在 bash 中可用但在 dash / sh 中不可用,在 Debian /bin/sh 下会静默失败。

常用写法

POSIX 便携 printf

在任何 POSIX shell 中均可工作 —— bash、dash、ash、ksh、mksh、busybox sh。#!/bin/sh 脚本应使用此形式。

printf '\033[1;31m%s\033[0m %s\n' 'error:' 'permission denied'
ANSI-C 引用($'…')

仅 bash 与 zsh —— 但可读性无可替代。\e 仅在 $'…' 中展开为 ESC 字节,普通 '…' 与 "…" 不展开。

red=$'\e[31m'
bold=$'\e[1m'
reset=$'\e[0m'
echo "${bold}${red}error:${reset} permission denied"
通过 tput 查询 terminfo

tput 根据当前 $TERM 解析能力名,同一脚本可在 dumb / 16 色 / 256 色终端上正常降级。

RED=$(tput setaf 1)
BOLD=$(tput bold)
RESET=$(tput sgr0)
printf '%s%serror:%s permission denied\n' "$BOLD" "$RED" "$RESET"
echo -e(便携脚本应避免)

Bash 仅在传入 -e 时解释反斜杠转义。dash / POSIX 模式 sh 会把 -e 当作字面参数输出,转义不会展开;请用 printf 或 $'…' 代替。

# Works in bash …
echo -e '\033[31merror\033[0m'
# … breaks under dash / sh — outputs literal: -e \033[31merror\033[0m
Zsh

在 Zsh 中使用 ANSI 转义码

Zsh 继承了 bash 的 ANSI-C 引用($'\e[…]'),并增加了 prompt 展开快捷形式 —— %F{red}…%f 表示前景色、%B…%b 表示加粗、%K{blue}…%k 表示背景色 —— 仅在 $PS1 / $PROMPT / $RPROMPT 中或 print -P 之后展开。在 prompt 之外,请像 bash 一样使用:$'\e[31m' 或 printf '\033[31m…'。autoload colors 模块提供命名数组 $fg / $bg / $reset_color,可读性更好。

常用写法

$PS1 中的 prompt 展开

%F{name}…%f / %B…%b / %K{name}…%k 仅在 prompt 内展开。仅当混合 zsh 无法计算宽度的原始 \e 码时,才需要 %{…%} 包裹。

# In ~/.zshrc
PS1='%B%F{green}%n@%m%f%b:%F{blue}%~%f%# '
print -P 在 $PS1 之外展开 prompt 码

同样的 %F{red}…%f 简写,可在脚本任意位置着色,无需写出 SGR 字节。

print -P '%F{red}error:%f permission denied'
通过 ANSI-C 引用输出原始 ESC

需要完整 SGR 控制(truecolor、OSC 等)时 prompt 码无法覆盖 —— 改用字面转义。

local red=$'\e[38;2;255;120;120m'
local reset=$'\e[0m'
echo "${red}truecolor red${reset}"
autoload colors —— 命名 SGR 数组

加载 $fg / $fg_bold / $bg / $reset_color 关联数组,让脚本以英文而非 SGR 数字呈现。

autoload -U colors && colors
echo "${fg[red]}error:${reset_color} permission denied"
Fish

在 Fish 中使用 ANSI 转义码

Fish 不提供 $'…' 或 \e 展开 —— 单双引号都不解释反斜杠转义。原生方案是 set_color,一个接受颜色名(red、blue、brmagenta)或 24 位十六进制(cba6f7)的内建命令,并支持 --bold / --italic / --underline / --background 等参数。少数需要原始字节(OSC、DCS 等)的情况可用 printf '\e[…]'。

常用写法

set_color —— 原生写法

直接管道发送颜色变更;用 set_color normal 重置。源码中无任何转义字面量。

set_color red
echo "error: permission denied"
set_color normal
通过 begin/end 或命令替换内联

行内颜色切换需把 set_color 输出捕获到 echo 参数中。

echo (set_color red)"error:"(set_color normal)" permission denied"
Truecolor(24 位)十六进制

十六进制参数底层发送 SGR 38;2;R;G;B。与 --background 搭配可同时控制前景与背景。

set_color cba6f7 --bold
echo "lavender bold"
set_color normal
OSC / DCS / 非 SGR 码的原始 ESC

set_color 未覆盖的字节(窗口标题、超链接、备用屏幕)请回退到 printf。

# Set window title via OSC 0
printf '\e]0;%s\a' "$argv[1]"
PowerShell

在 PowerShell 中使用 ANSI 转义码

PowerShell 7.2+ 内置 $PSStyle —— 一个将每个 SGR 颜色与属性暴露为属性的对象($PSStyle.Foreground.Red、$PSStyle.Bold、$PSStyle.Reset)。底层发送 ANSI,并遵守 $PSStyle.OutputRendering 控制重定向时的输出。Windows PowerShell 5.1(仍随 Windows 10/11 一起发布)没有 $PSStyle;标准变通方案是用 [char]27 构造 ESC 字节,或在 PS 6+ 中使用 `e(反引号 e)双引号字符串。Write-Host -ForegroundColor 走的是主机 console API,不是 ANSI,因此不能与 $PSStyle 组合,重定向时会被剥离。

常用写法

$PSStyle(PowerShell 7.2+)

现代语义化 API —— 自动重置、感知重定向、可组合。新代码请优先使用。

"$($PSStyle.Bold)$($PSStyle.Foreground.Red)error:$($PSStyle.Reset) permission denied"
[char]27(Windows PowerShell 5.1 及更早)

ESC 的十进制值是 27。先存入 $e,之后像普通字符串一样拼接转义序列。

$e = [char]27
"$e[1;31merror:$e[0m permission denied"
双引号字符串中的 `e(PowerShell 6+)

反引号 e 是 PowerShell 的 ESC 转义 —— 不能用 $PSStyle 时最简洁的写法。

"`e[1;31merror:`e[0m permission denied"
$PSStyle.OutputRendering —— 重定向时剥离 ANSI

默认 Host 模式:终端输出 ANSI,重定向 / 管道输出剥离。设为 Ansi 强制输出,PlainText 完全禁用。

$PSStyle.OutputRendering = 'Ansi'      # always emit, even when redirected
$PSStyle.OutputRendering = 'PlainText' # never emit
$PSStyle.OutputRendering = 'Host'      # default: terminal yes, redirect no
cmd.exe (batch)

在 cmd.exe / 批处理中使用 ANSI 转义码

cmd.exe 自 Windows 10 build 14393(Anniversary Update,2016)起支持 ANSI,并在任何 ConPTY 感知的主机上默认启用 —— Windows Terminal、VS Code 终端、Cursor、Hyper。通过 Win+R cmd 打开的传统 conhost.exe 窗口是否启用 ANSI 取决于 Windows 版本及每窗口的 VT 处理标志。批处理本身没有干净的 ESC 字节语法:要么用能保存 0x1b 字节的编辑器把字面字符嵌入 .bat 文件,要么使用 for /f prompt $H 技巧。任何稍复杂的场景,建议从批处理里调用 PowerShell(powershell -NoProfile -Command "…")代替。

常用写法

用 for /f + prompt $H 嵌入字面 ESC

黑魔法批处理写法 —— $H 是 prompt 的退格令牌,for /f 循环捕获单字节,经裁剪后作为 ESC 使用。源自 Microsoft 官方 ConPTY 示例。

@echo off
for /f %%a in ('echo prompt $E ^| cmd') do set "ESC=%%a"
echo %ESC%[1;31merror:%ESC%[0m permission denied
先切到 UTF-8 代码页 —— chcp 65001

与 ANSI 无关但几乎总是配套使用:chcp 65001 让 cmd 以 UTF-8 解析脚本与输出(默认是 OEM 437 / 936 等)。

@echo off
chcp 65001 > nul
echo Multilingual: αβγ • 中文 • emoji 🚀
复杂样式委托给 PowerShell

需要多于一两行彩色输出时,调用 PowerShell 更短、更可读,并在每个 Windows 主机上行为一致。

@echo off
powershell -NoProfile -Command "Write-Host \"$([char]27)[1;31merror:$([char]27)[0m permission denied\""

参见

/use 覆盖库层(chalk、fatih/color、rich、ncurses)。本页是 shell 语法层 —— 在 dotfile 里如何拼写一条转义。terminfo 把 tput 能力映射到这些 shell 最终发送的字节;pitfalls 收录所有「语法没问题但运行时仍然坏掉」的情况。