Linux终端控制与ANSI转义序列

1 前言

在Windows系统中,我们可以通过系统提供的接口操作控制台缓冲区的显示。那么在linux平台应该如何实现呢?答案就是ANSI转义序列
在计算机系统中,ANSI转义码(或转义序列)是一种使用带内信号控制视频文本终端的格式、颜色和其他输出选项的方法。
为了编码这种格式化信息,特定的字节序列被嵌入到文本中,终端将查找并将其解释为命令,而不是字符代码。

2 CSI

实际上,ANSI转义序列的范围比较大,包括ASCII码表中的被称为Control characters 控制字符(C0代码)之外,还包括了ESC字符开头的C1代码。
而这里介绍的就是C1代码中最常用的部分CSI序列
ANSI转义序列中以 ESC [ 开头的叫作 Control Sequence Introducer,简写为 CSI
以 CSI 开头的指令有很多,大致可分四类:光标控制、屏幕控制、和字符渲染(Graphic Rendition)指令。
CSI序列的语法如下所示:

0x1B + "[" + [[0-9]*[;]] + <fun>
  • 开始,0x1B 是ansi escape code开始的标准
  • 其次,[ 是CSI (Control Sequence Introducer)
  • 然后,中间部分由0个或者多个数字组成,是函数的参数,多个参数之间由分号进行分割
  • 最终,一个字母代表需要调用的函数名

CSI (Control Sequence Introducer) 各部分的字符范围如下:

组成部分 字符范围 ASCII
参数字节 0x30–0x3F 0–9:;<=>?
中间字节 0x20–0x2F 空格、!"#$%&’()*+,-./
最终字节 0x40–0x7E @A–Z[]^_`a–z{
2.1 光标控制
控制码 说明
\033[nA 光标上移 n(默认1) 行 <<若至屏幕顶端则无效>>
\033[nB 光标下移 n (默认1)行 <<若至屏幕底端则无效>>
\033[nC 光标前移 n (默认1)列 <<若至屏幕右端则无效>>
\033[nD 光标后退 n (默认1)列 <<若至屏幕左端则无效>>
\033[nE 光标下移 n (默认1)行 <<非标准>>
\033[nF 光标上移 n (默认1)行 <<非标准>>
\033[nG 光标移动至当前行n(默认1)列 <<非标准>>
\033[x;yH 光标移动至x行y列(默认从1开始,左上角)
\033[s 保存光标位置
\033[u 取出保存的光标位置来使用
\033[?25l 隐藏光标
\033[?25h 显示光标
2.2 屏幕控制
控制码 说明
\033[nJ 清除指定范围屏幕。0:光标位置至屏幕末尾;1:光标位置至屏幕开头;2:全屏幕
\033[nK 擦除行中指定范围列。0:光标位置至行尾;1:光标位置至行头;2:整行
\033[nS 整页向上滚动n行。<<非标准>>
\033[nT 整页向下滚动n行。<<非标准>>
2.3 字符渲染

字符渲指令全称 Select Graphic Rendition,简写为 SGR。其格式为 CSI n m,以数字开头,并以 m 结尾,n 的取值范围是 0-107。又可以分成两类,一类控制字符显示样式,另一类控制显示颜色。

代码 含义
0 所有属性 OFF,即返回正常显示模式 (Normal)
1 粗体(Bold)/高亮度显示 (Bright)
3 斜体(未广泛支持)
4 下划线
5 闪烁显示
7 反显(前景色与背景色交换)
39 默认前景色
49 默认背景色

设置颜色:

前景 背景 颜色
30 40 黑色
31 41 红色
32 42 绿色
33 43 黄色
34 44 蓝色
35 45 紫红色
36 46 青蓝色
37 47 白色

3 示例

3.1 清除屏幕
  printf("\x1b[2J"); // 清屏幕
  printf("\x1b[?25l"); // 设置光标不可见
3.2 禁用回显
  struct termios setting;
  tcgetattr(STDIN_FILENO, &setting); // 禁用回显
  setting.c_lflag &= ~ECHO;
  tcsetattr(STDIN_FILENO, TCSANOW, &setting);
3.3 获取标准输入
  fd_set io;
  FD_SET(STDIN_FILENO, &io);
  timeval timeout = {sec, usec};
  select(STDIN_FILENO + 1, &io, NULL, NULL, &timeout); // 监听标准输入

  char cmd[10] = {0};
  read(STDIN_FILENO, cmd, sizeof(cmd)); // read读取标准输入避免循环getc阻塞
3.4 数据输出到屏幕
  printf("\x1b[2;1H"); // 光标定位至第二行开头
  printf("\x1b[30;47m"); // 设置白底黑字
  fill(header, strlen(header)); // 输出
  printf("\x1b[39;49m"); // 设置默认颜色

// 光标移动至指定行的行首
void move(int y) { printf("\x1b[%d;1H", y); }

// 输出字符串同时清除光标后的列
void print(const char* str) { printf("%s\x1b[K", str); }

4 完整示例

平台实现简单的进程信息查看。simple_taskmgr

你可能感兴趣的:(ANSI转义序列,linux,ansi转义序列)