彩色终端输出不复位

Colored terminal output does not reset

在编写较大的程序时,我偶然发现了彩色文本输出的一个小问题。这是重现此问题的更简单的程序。

#include <stdio.h>

#define COL_RESET "3[0m"
#define COL_BG_RED  "\x1B[41m"

char *str = "the quick brown fox jumped over the lazy dog";

int main(int argc, char *argv[])
{
    int i = 10;
    while (i) {
        puts(COL_BG_RED);
        puts(str);
        puts(COL_RESET);
        puts(str);
        i--;
    }
    return 0;
}

现在这是我 运行 程序得到的结果:

第一次 - 预期结果

第二次

如您所知,即使在将颜色重置为红色后,程序仍决定随机打印线条。当在一个新的终端启动时,它总是打印出预期的结果。除非我 运行 clear,否则不能保证输出不会像第二张图片那样被破坏。

在我使用的图片中xterm,尽管其他终端也做同样的事情。

我能做些什么来防止这种情况发生?

问题似乎是在终端开始滚动时出现的。

问题可能是puts追加了一个换行符引起的。使用 printf.

修改您的代码
printf(COL_BG_RED);
printf(str);
puts(COL_RESET);
puts(str);

当我在本地 运行 时,我也观察到一些奇怪的行为。

使用:

#define COL_RESET      "[=10=]x1b[39;49m" // reset fore/back ground to normal
#define COL_BG_RED     "3[41m"

输出:

#define 更改为使用八进制而不是十六进制时,我得到了不同的(预期的)结果。

使用:

#define COL_RESET "3[39;49m"

输出:

您也可以考虑创建一个宏来使用 printf 颜色。

#include <stdio.h>

#define COL_RESET      "3[39;49m"
#define COL_BG_RED     "3[41m"
#define COL_BG_NORMAL  "3[49m"

#define COLOR_NORMAL    "3[m"
#define COLOR_RESET     "3[0m"
#define COLOR_BLACK     "3[30m"
#define COLOR_RED       "3[31m"
#define COLOR_GREEN     "3[32m"
#define COLOR_YELLOW    "3[33m"
#define COLOR_BLUE      "3[34m"
#define COLOR_MAGENTA   "3[35m"
#define COLOR_CYAN      "3[36m"
#define COLOR_WHITE     "3[37m"

#define COLOR_PRINTF(colorCode,fmt,...) printf("%s" fmt "%s", colorCode, __VA_ARGS__, COL_RESET)

char *str = "the quick brown fox jumped over the lazy dog";

int main(int argc, char *argv[])
{
    int i = 1;
    while (i) {
        COLOR_PRINTF(COLOR_GREEN, "%s\n", str);
        COLOR_PRINTF(COL_BG_RED, "%s\n", str);
        i--;
    }
    return 0;
}

如评论所述,这是一些知名终端的已知行为:滚动(或反向滚动)时,屏幕上新清除的区域会填充当前背景色。 Linux 控制台执行此操作(除了几年前的一个故障,在 terminal database). xterm does it.

中指出

在 ncurses 中,几个相关的行为被集中在一起作为 bce(背景颜色擦除)功能:

  • 填充由于滚动而新清除的行
  • 擦除显示,同时擦除以光标结束或开始的部分。
  • 擦除一行,或擦除光标到行尾或从光标到行尾的部分
  • 正在光标位置插入(一个空格)
  • 删除一个字符

通常 ncurses 会填空(只有当终端输入 poorly chosen 时才会出现问题),您不会看到这一点。但是使用简单的转义序列意味着您可以稍微探索 bce 的细微差别。

直接使用转义序列打印颜色的终端应用程序应在写入 任何 其他不打算着色的文本之前重置颜色。其他应用程序(例如 shell 中的行编辑)在擦除行内的文本时必须牢记此规则