2023-09-07    2023-09-07    1828 字  4 分钟

最近在在改进站点的部署脚本,调试的时候有一些中间状态信息想要高亮显示,就需要对终端 Terminal 字符的输出样式进行修改,如何修改呢?往下看。

修改终端字符输出样式

Bash 命令 输出预览
echo "hello world" image-20230907140443099
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" image-20230907135513374

如上表中所描述的这样,我们改变了输出字符的字体颜色(前景色)和背景颜色(后景色)。通常,达到这种效果,已经满足了我此次的需求。它是怎么实现的呢?

在终端中运行 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 相当于中间的数字是 0ESC[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;n2;r;g;b ,见下。
39 默认前景色 由具体实现定义(按照标准)。
40–47 设置背景色 参见下面的颜色表。 image-20230907135513374
48 设置背景色 下一个参数是 5;n2;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]]

到这里,你基本上已经可以轻松地实现实现你想输出的字符效果了。🎉

参考