最近在在改进站点的部署脚本,调试的时候有一些中间状态信息想要高亮显示,就需要对终端 Terminal 字符的输出样式进行修改,如何修改呢?往下看。
修改终端字符输出样式
Bash 命令 | 输出预览 |
---|---|
echo "hello world" |
|
echo -e "\e[31mHello World\e[0m" |
![[assets/Pasted image 20230907120819.png]] |
echo -e "\e[31mHello\e[0m World" |
![[assets/Pasted image 20230907120736.png]] |
echo -e "\e[31;47mHello\e[0m World" |
如上表中所描述的这样,我们改变了输出字符的字体颜色(前景色)和背景颜色(后景色)。通常,达到这种效果,已经满足了我此次的需求。它是怎么实现的呢?
在终端中运行 help echo
,我们可以看到 echo
命令的简要使用说明,部分如下:
$ help echo
echo: echo [-neE] [arg ...]
Write arguments to the standard output.
Display the ARGs, separated by a single space character and followed by a
newline, on the standard output.
Options:
-e enable interpretation of the following backslash escapes
允许解释后面的反斜杠转义
-E explicitly suppress interpretation of backslash escapes
禁止解释后面的反斜杠转义
`echo' interprets the following backslash-escaped characters:
\e escape character
<Esc>
...
Exit Status:
Returns success unless a write error occurs.
现在我们明白了, -e
就是‘允许解释后面的反斜杠转义’,而 \e
代表的是 <Esc>
。
echo "hello world"
echo -e "\e[31mHello World\e[0m"
echo -e "\e[31mHello\e[0m World"
echo -e "\e[31;47mHello\e[0m World"
我们再来分析一下这个格式,排除直接输出的字符 hello world ,就是诸如 \e[31m
、\e[0m
、\e[31;47m
这种字符,改变字符输出样式的就是它们了!
那么,它们是什么呢?CSI !
CSI
CSI(Control Sequence Introducer,控制顺序介接子;控制序列引导码)。
CSI 序列由 ESC [
(又写作 \e[
或 \033
)、若干个(包括 0 个)“参数字节”、若干个“中间字节”,以及一个“最终字节”组成。
:: 没那么复杂,起码不需要记得那么复杂,知道用
\e[
来引导一个 CSI 序列就可以了。
所有常见的序列都只是把参数用作一系列分号分隔的数字,如 1;2;3
。缺少的数字视为 0
(如 1;;3
相当于中间的数字是 0
,ESC[m
这样没有参数的情况相当于参数为 0
)。
CSI 是 ANSI 转义序列的一种,后者是一种带内信号的转义序列标准,用于控制视频文本终端上的光标位置、颜色和其他选项。
ANSI Escape Sequences - 在文本中嵌入确定的字节序列,大部分以
Esc [
字符开始,终端会把这些字节序列解释为相应的指令,而不是普通的字符编码。
在 CSI 中,参数方式 CSI n m
(如 \e31m
), 称为 SGR 。
SGR
SGR (Select Graphic Rendition,选择图形再现),通过设置相应参数,以改变字符输出样式,如字体颜色、背景着色、粗体、斜体等等。
其部分常用参数如下:
代码 | 作用 | 备注 | 示例 |
---|---|---|---|
0 | 重置/正常 | 关闭所有属性。 | |
1 | 粗体或增加强度 | ||
2 | 弱化(降低强度) | 未广泛支持。 | |
3 | 斜体 | 未广泛支持。有时视为反相显示。 | |
4 | 下划线 | ||
5 | 缓慢闪烁 | 低于每分钟 150 次。 | |
6 | 快速闪烁 | MS-DOS ANSI. SYS;每分钟 150 以上;未广泛支持。 | |
7 | 反显 | 前景色与背景色交换。 | |
8 | 隐藏 | 未广泛支持。 | |
9 | 划除 | 字符清晰,但标记为删除。未广泛支持。 | |
10 | 主要(默认)字体 | ||
21 | 关闭粗体或双下划线 | 关闭粗体未广泛支持;双下划线几乎无支持。 | |
22 | 正常颜色或强度 | 不强不弱。 | |
23 | 非斜体、非尖角体 | ||
24 | 关闭下划线 | 去掉单双下划线。 | |
25 | 关闭闪烁 | ||
27 | 关闭反显 | ||
28 | 关闭隐藏 | ||
29 | 关闭划除 | ||
30–37 | 设置前景色 | 参见下面的颜色表。 | ![[assets/Pasted image 20230907120819.png]] |
38 | 设置前景色 | 下一个参数是 5;n 或 2;r;g;b ,见下。 |
|
39 | 默认前景色 | 由具体实现定义(按照标准)。 | |
40–47 | 设置背景色 | 参见下面的颜色表。 | |
48 | 设置背景色 | 下一个参数是 5;n 或 2;r;g;b ,见下。 |
|
49 | 默认背景色 | 由具体实现定义(按照标准)。 |
认真观察 1-9 和 21-29 ,它们一一对应,后者恰好是关闭前者的效果。下面让我们把注意力放在前景色和背景色上,看一下,它们是怎么分配的。
初始的规格只有 8 种颜色,只给了它们的名字。SGR 参数 30-37 选择前景色,40-47 选择背景色。
相当多的终端将“粗体”(SGR 代码 1)实现为更明亮的颜色而不是不同的字体,从而提供了 8 种额外的前景色,但通常情况下并不能用于背景色,虽然有时候反显(SGR 代码 7)可以允许这样。例如:在白色背景上显示黑色文字使用
ESC[30;47m
,显示红色文字用ESC[31m
,显示明亮的红色文字用ESC[1;31m
。重置为默认颜色用ESC[39;49m
(某些终端不支持),重置所有属性用ESC[0m
。后来的终端新增了功能,可以直接用 90-97 和 100-107 指定“明亮”的颜色。
![[assets/Pasted image 20230907152530.png]]
> 3/4 位 8 色 - 黑、红、绿、黄、蓝、品红、青、白
随着256色查找表在显卡上越来越常见,相应的转义序列也增加了,以从预定义的256种颜色中选择。总之,原理是一样的。如:
Bash 命令 | 输出预览 |
---|---|
echo -e "\e[38;5;183mhello world\e[m" |
![[assets/Pasted image 20230907154854.png]] |
echo -e "\e[48;5;125mhello world\e[m" |
![[assets/Pasted image 20230907154936.png]] |
\e[38;5;183m
![[assets/Pasted image 20230907154428.png]]
> 8 位 256 色模式
如果,你不想记这么多颜色号,但是恰好熟悉 RGB ,那么,你也可以使用它 (如 \e[38;2;R;G;Bm
)来方便地设置颜色,如:
Bash 命令 | 输出预览 |
---|---|
echo -e "\e[38;2;255;1;1mhello world\e[m" |
![[assets/Pasted image 20230907120819.png]] |
echo -e "\e[48;2;255;1;1mhello world\e[m" |
![[assets/Pasted image 20230907154252.png]] |
到这里,你基本上已经可以轻松地实现实现你想输出的字符效果了。🎉