如何在命令行中显示五彩斑斓的“黑”

3,137 阅读4分钟

1. 前言

大部分 coder 已经习惯了命令行枯燥的黑底白字,而且任何编程语言入门的第一行代码都是教我们如何在标准输出(大部分情况就是命令行终端或控制台)打印一行“非黑即白”的 hello world! 。以至于很多不懂编程的“大佬”都觉得程序猿们都TM奇了个葩了,整天对着一块黑屏,瞎JB敲来敲去,还TM当个宝似的。那么本文将告诉你,这不仅仅是一块黑屏,它还能黑得五彩斑斓,亮瞎🐶眼。。。哈哈哈。。。下图为本文最终能达到的效果,提前贴出来,以表示我没有在吹🐂B。

2. ANSI 转义序列 (ANSI Escape sequences)

要在黑白电视机般的命令行终端显示五彩斑斓的文字,就不得不先知道它的实现机制,即用于设置文本属性和颜色的 ANSI 转义序列

2.1 什么是 ANSI 转义序列 ?

ANSI 转义序列有些地方也叫 ANSI 转义码(ANSI Escape codes)。它是由 ASCII 码字符组成的序列,用于实现在命令行终端改变图形显示和控制光标移动。

它的前两个字符固定是:

  • 转义字符 Esc,ASCII 码为 27 (十六进制:0x1b)
  • 左中括号字符 [,ASCII 码为 91 (十六进制:0x5b)

后跟控制键盘和显示功能的字母数字码(区分大小写)。这里我们只讨论与显示相关的转义序列,即设置图形显示模式。

2.2 使用 ANSI 转义序列设置图形显示模式

格式(注意以字符m收尾):

Esc[Value;...;Valuem

支持设置的显示模式包含文本属性,前景色和背景色。

2.2.1 文本属性

Value 文本属性
0 重置所有属性
1 粗体显示
4 下划线
5 文字闪烁
7 反向显示
8 隐藏

2.2.2 前景色

Value 颜色
30
31
32 绿
33
34
35 品红
36
37

2.2.3 背景色

Value 颜色
40
41
42 绿
43
44
45 品红
46
47

3. python 实现

理解了 ANSI 转义序列的工作机制,使用任何编程语言都可以实现在命令行终端显示不同颜色的文字和背景色。以 python 为例,一般我们使用 print() 函数,传入字符串,就会向标准输出打印出熟悉的黑底白字,但如果在传入的字符串前加上控制显示的 ANSI 转义序列,就能按照我们设置的显示模式来显示了。

3.1 使用 print() 打印 ANSI 转义序列

我们通过给 print() 传入 ANSI 转义序列 + 要显示的字符串 方式来控制文本的显示模式。需要注意的是 ANSI 转义序列 的第一个字符 Esc 是不可打印字符,我们需要以 unicode 转义字符的形式表示, Esc 的 unicode 表示为 \u001b ; 此外,设置图像显示模式,不要忘记了 ANSI 转义序列 结尾处的字符 m,可以将 m 看做控制显示模式的序列与要显示文本的分隔符。

显示红色 "hello world!" :

print("\u001b[31m hello world!")

3.2 同时设置文本属性+前景色+背景色

由前文图形显示模式的 ANSI 转义序列 格式可以看出,支持一次设置多个 Value,多个 Value 用分号隔开。由于属性,同一种颜色的前景和背景色 Value 都是不同的,所以他们设置的顺序也没有要求。例如,显示绿底白字闪烁的“hello world!” 。

print("\u001b[42;37;5m hello world!")

3.3 重置所有属性

细心的读者应该注意到,在设置新的显示属性前,之前设置的属性会一直保留,即使是命令行提示符也会受到影响。那么为了每次设置的属性只影响当前的显示,就需要在要显示的文本后加上重置所有属性的转义序列 \u001b[0m

print("\u001b[34;1m hello world! \u001b[0m")

print("\u001b[41;37m hello \u001b[0m \u001b[32;4m world! \u001b[0m")

3.4 256 种颜色的扩展颜色集

前面介绍的不管是前景色还是背景色包含黑白两色,也只有8种颜色,而且如果对审美有较高要求,这些颜色一点也不优雅。还好我们还有其他颜色可选,但只有部分终端支持。笔者只测试了 MacOs ,其他平台的终端,读者可以自行尝试。

扩展颜色集转义序列格式:

"\u001b[38;5;${ID}m"

示例:

for i in range(0, 16):
    line = ""
    for j in range(0, 16):
        code = str(i * 16 + j)
        line += "\u001b[38;5;" + code + "m " + code.ljust(4)
    print(line)
    print("\u001b[0m")

当然也支持背景色,只需要将 38 改成 48:

"\u001b[48;5;${ID}m"

示例:

for i in range(0, 16):
    line = ""
    for j in range(0, 16):
        code = str(i * 16 + j)
        line += "\u001b[48;5;" + code + "m " + code.ljust(4)
    print(line)
    print("\u001b[0m")

4. Nodejs 实现

参考 《nodejs 打印五彩斑斓的"黑"》

The End

命令行中显示五彩斑斓的“黑”就是这么简单!

Thanks

如果本文对你有帮助,请不要吝惜点赞哦 👍

【阅读原文】


微信扫描二维码 获取最新技术原创