在 Ubuntu 终端输出不同颜色、粗体、下划线或其他样式的字体

嗯。调试时总发现自己打印的调试信息太过普通、单调,于是乎......

Notice

要在终端实现字体的特殊样式,通常通过使用特殊的控制字符来实现,而不是通过某语言本身的功能来实现。

在大多数终端中,可以使用 ANSI 转义序列来设置字体的颜色。ANSI 转义序列是一系列以 ESC 开头的字符,用于控制文本终端的属性,包括颜色、格式和光标位置等。ANSI 转义序列以 \033[ 开头,后跟属性代码,以设置不同的终端属性。
请注意,不同的终端可能对 ANSI 转义序列的支持程度不同。大多数 Unix/Linux 终端和 Windows 上的一些控制台仿真器(如 ConEmu、Cygwin 和 Windows Terminal)都支持 ANSI 转义序列。

Color

包括前景色和背景色。前景色指的是字体本身的颜色,背景色指的是字体的背景颜色。

一些常见颜色:黑色、红色、绿色、黄色、蓝色、洋红色、青色、白色。

先来看一下效果:

#define

见名知意,不再赘述。

cpp 复制代码
#define ANSI_COLOR_RESET   "\x1b[0m"		// 重置

#define ANSI_COLOR_BLACK   "\033[30m"		// 前景色
#define ANSI_COLOR_RED     "\x1b[31m"
#define ANSI_COLOR_GREEN   "\x1b[32m"
#define ANSI_COLOR_YELLOW  "\x1b[33m"
#define ANSI_COLOR_BLUE    "\x1b[34m"
#define ANSI_COLOR_MAGENTA "\x1b[35m"
#define ANSI_COLOR_CYAN    "\x1b[36m"
#define ANSI_COLOR_WHITE   "\033[37m"

#define ANSI_BG_BLACK       "\x1b[40m"		// 背景色
#define ANSI_BG_RED         "\x1b[41m"
#define ANSI_BG_GREEN       "\x1b[42m"
#define ANSI_BG_YELLOW      "\x1b[43m"
#define ANSI_BG_BLUE        "\x1b[44m"
#define ANSI_BG_MAGENTA     "\x1b[45m"
#define ANSI_BG_CYAN        "\x1b[46m"
#define ANSI_BG_WHITE       "\x1b[47m"

#define ANSI_COLOR_BRIGHT_BLACK   "\x1b[90m"		// 前景亮色
#define ANSI_COLOR_BRIGHT_RED     "\x1b[91m"
#define ANSI_COLOR_BRIGHT_GREEN   "\x1b[92m"
#define ANSI_COLOR_BRIGHT_YELLOW  "\x1b[93m"
#define ANSI_COLOR_BRIGHT_BLUE    "\x1b[94m"
#define ANSI_COLOR_BRIGHT_MAGENTA "\x1b[95m"
#define ANSI_COLOR_BRIGHT_CYAN    "\x1b[96m"
#define ANSI_COLOR_BRIGHT_WHITE   "\x1b[97m"

#define ANSI_BG_BRIGHT_BLACK       "\x1b[100m"		// 背景亮色
#define ANSI_BG_BRIGHT_RED         "\x1b[101m"
#define ANSI_BG_BRIGHT_GREEN       "\x1b[102m"
#define ANSI_BG_BRIGHT_YELLOW      "\x1b[103m"
#define ANSI_BG_BRIGHT_BLUE        "\x1b[104m"
#define ANSI_BG_BRIGHT_MAGENTA     "\x1b[105m"
#define ANSI_BG_BRIGHT_CYAN        "\x1b[106m"
#define ANSI_BG_BRIGHT_WHITE       "\x1b[107m"

Example

cpp 复制代码
#include <iostream>

// 有的宏定义没有用到,但懒得删掉了 ×_×

#define ANSI_COLOR_BLACK   "\033[30m"
#define ANSI_COLOR_RED     "\x1b[31m"
#define ANSI_COLOR_GREEN   "\x1b[32m"
#define ANSI_COLOR_YELLOW  "\x1b[33m"
#define ANSI_COLOR_BLUE    "\x1b[34m"
#define ANSI_COLOR_MAGENTA "\x1b[35m"
#define ANSI_COLOR_CYAN    "\x1b[36m"
#define ANSI_COLOR_WHITE   "\033[37m"

#define ANSI_COLOR_RESET   "\x1b[0m"

#define ANSI_BG_BLACK       "\x1b[40m"
#define ANSI_BG_RED         "\x1b[41m"
#define ANSI_BG_GREEN       "\x1b[42m"
#define ANSI_BG_YELLOW      "\x1b[43m"
#define ANSI_BG_BLUE        "\x1b[44m"
#define ANSI_BG_MAGENTA     "\x1b[45m"
#define ANSI_BG_CYAN        "\x1b[46m"
#define ANSI_BG_WHITE       "\x1b[47m"

#define ANSI_COLOR_BRIGHT_RED     "\x1b[91m"
#define ANSI_COLOR_BRIGHT_GREEN   "\x1b[92m"
#define ANSI_COLOR_BRIGHT_YELLOW  "\x1b[93m"
#define ANSI_COLOR_BRIGHT_BLUE    "\x1b[94m"
#define ANSI_COLOR_BRIGHT_MAGENTA "\x1b[95m"
#define ANSI_COLOR_BRIGHT_CYAN    "\x1b[96m"
#define ANSI_COLOR_BRIGHT_WHITE   "\x1b[97m"

#define ANSI_BG_BRIGHT_BLACK      "\x1b[100m"

int main() {

    std::cout << "\033[31mThis text will be red. \033[0m" << std::endl;
    std::cout << "\x1b[33mThis text will be yellow. \033[0m" << std::endl;
    std::cout << ANSI_COLOR_RED << ANSI_BG_YELLOW << "Hello, world!" << ANSI_COLOR_RESET << std::endl;
    std::cout << ANSI_BG_GREEN << ANSI_BG_MAGENTA << "¡Hola, mundo!" << ANSI_COLOR_RESET << std::endl;
    std::cout << ANSI_BG_YELLOW << ANSI_BG_CYAN << "Hallo, welt!" << ANSI_COLOR_RESET << std::endl;
    std::cout << ANSI_COLOR_BRIGHT_BLUE << "Your future will be bright!" << ANSI_COLOR_RESET << std::endl;
    std::cout << ANSI_COLOR_BLUE << "Your future will be bright!" << ANSI_COLOR_RESET << std::endl;

    std::cout << ANSI_COLOR_WHITE << "This is white. " << ANSI_COLOR_RESET << std::endl;
    std::cout << ANSI_COLOR_BRIGHT_WHITE << "This is bright white. " << ANSI_COLOR_RESET << std::endl;

    std::cout << ANSI_COLOR_WHITE << ANSI_BG_BRIGHT_BLACK << "BrightBlack. " << ANSI_COLOR_RESET << std::endl;
    std::cout << ANSI_COLOR_WHITE << ANSI_BG_BLACK << "Black. " << ANSI_COLOR_RESET << std::endl;

    return 0;
}

outcome

实现效果如下:

ROS_INFO

那么如何使用 ROS_INFO 来输出彩色字体呢?

cpp 复制代码
	// 创建一个字符串流
    std::stringstream ss;
    
    // 向字符串流中添加需要的信息和 ANSI 转义序列
    ss << "\x1b[31m\x1b[43m" << "Hello, world!" << "\x1b[0m";
    
    // 使用 ROS_INFO 输出字符串流中的内容
    ROS_INFO("%s", ss.str().c_str());

以上代码来自 GPT。但保险起见,在向流中添加信息和转义序列时,尤其需要反复使用同一字符串流时,最好先执行以下操作:

cpp 复制代码
ss.str("");

Bold & Underline

#define

见名知意,不再赘述。

cpp 复制代码
#define ANSI_BOLD_ON        "\x1b[1m"
#define ANSI_BOLD_OFF       "\x1b[22m"

#define ANSI_UNDERLINE_ON   "\x1b[4m"
#define ANSI_UNDERLINE_OFF  "\x1b[24m"

#define ANSI_COLOR_RESET    "\x1b[0m"

Example

cpp 复制代码
#include <iostream>

// ANSI 转义序列,用于设置字体加粗和取消加粗
#define ANSI_BOLD_ON      "\x1b[1m"
#define ANSI_BOLD_OFF     "\x1b[22m"

// ANSI 转义序列,用于设置下划线和取消下划线
#define ANSI_UNDERLINE_ON   "\x1b[4m"
#define ANSI_UNDERLINE_OFF  "\x1b[24m"

// ANSI 转义序列,用于重置终端颜色
#define ANSI_COLOR_RESET    "\x1b[0m"

int main() {
    // 输出加粗文字
    std::cout << ANSI_BOLD_ON << "Bold Text" << ANSI_COLOR_RESET << std::endl;
    // 输出带下划线的文字
    std::cout << ANSI_UNDERLINE_ON << "Underlined Text" << ANSI_COLOR_RESET << std::endl;

    return 0;
}

outcome

实现效果如下:

ROS_INFO

同上。

Other styles

#define

见名知意,不再赘述。

cpp 复制代码
#define ANSI_BLINK_ON       "\x1b[5m"   // 开启闪烁
#define ANSI_BLINK_OFF      "\x1b[25m"  // 关闭闪烁

#define ANSI_REVERSE_ON     "\x1b[7m"   // 开启反显
#define ANSI_REVERSE_OFF    "\x1b[27m"  // 关闭反显

#define ANSI_HIDDEN_ON      "\x1b[8m"   // 开启隐藏
#define ANSI_HIDDEN_OFF     "\x1b[28m"  // 关闭隐藏

#define ANSI_STRIKETHROUGH  "\x1b[9m"   // 开启删除线
#define ANSI_STRIKETHROUGH  "\x1b[99m"  // 关闭删除线

#define ANSI_RESET          "\x1b[0m"

Example

cpp 复制代码
#include <iostream>

// ANSI 转义序列,用于设置终端效果
#define ANSI_BLINK_ON       "\x1b[5m"   // 开启闪烁
#define ANSI_BLINK_OFF      "\x1b[25m"  // 关闭闪烁
#define ANSI_REVERSE_ON     "\x1b[7m"   // 开启反显
#define ANSI_REVERSE_OFF    "\x1b[27m"  // 关闭反显
#define ANSI_HIDDEN_ON      "\x1b[8m"   // 开启隐藏
#define ANSI_HIDDEN_OFF     "\x1b[28m"  // 关闭隐藏
#define ANSI_STRIKETHROUGH  "\x1b[9m"   // 开启删除线

// ANSI 转义序列,用于重置终端效果
#define ANSI_RESET          "\x1b[0m"

int main() {
    // 闪烁效果
    std::cout << ANSI_BLINK_ON << "Blinking Text" << ANSI_RESET << std::endl;
    std::cout << ANSI_BLINK_OFF << "No Blinking Text" << ANSI_RESET << std::endl;

    // 反显效果
    std::cout << ANSI_REVERSE_ON << "Reversed Text" << ANSI_RESET << std::endl;
    std::cout << ANSI_REVERSE_OFF << "No Reversed Text" << ANSI_RESET << std::endl;

    // 隐藏效果
    std::cout << ANSI_HIDDEN_ON << "Hidden Text" << ANSI_RESET << std::endl;
    std::cout << ANSI_HIDDEN_OFF << "No Hidden Text" << ANSI_RESET << std::endl;

    // 删除线效果
    std::cout << ANSI_STRIKETHROUGH << "Strikethrough Text" << ANSI_RESET << std::endl;

    return 0;
}

outcome

实现效果如下:

ROS_INFO

cpp 复制代码
#include <ros/ros.h>
#include <sstream>

// 自定义的打印函数,用于在ROS_INFO中使用特定标记实现效果
void customInfo(const std::string& message) {
    std::cout << message << std::endl;
}

int main(int argc, char** argv) {
    ros::init(argc, argv, "example_node");
    ros::NodeHandle nh;

    // 创建一个字符串流
    std::stringstream ss;
    // 向字符串流中添加需要的信息,并使用特定标记来表示效果
    ss << "[blink]Hello, world![/blink] ";
    ss << "[reverse]Reversed Text[/reverse] ";
    ss << "[hidden]Hidden Text[/hidden] ";
    ss << "[strikethrough]Strikethrough Text[/strikethrough]";
    // 使用自定义的打印函数打印信息
    customInfo(ss.str());

    ros::spin();
    return 0;
}

Combination

以上(并不互相冲突的)诸多效果可组合使用。略。

相关推荐
好奇的菜鸟7 小时前
如何在 Ubuntu 24.04 (Noble) 上使用阿里源
linux·运维·ubuntu
好奇的菜鸟9 小时前
如何在Ubuntu上检查MySQL是否启动并放开3306端口
mysql·ubuntu·adb
ZPC821012 小时前
ubuntu 6.8.0 安装xenomai3.3
linux·运维·ubuntu
电脑能手13 小时前
遇到该问题:kex_exchange_identification: read: Connection reset`的解决办法
linux·ubuntu·ssh
snoopyfly~14 小时前
Ubuntu 24.04 安装配置 Redis 7.0 开机自启
linux·redis·ubuntu
精英的英14 小时前
在Ubuntu 24.04主机上创建Ubuntu 14.04编译环境的完整指南
linux·运维·ubuntu
奇妙之二进制15 小时前
计算机科学导论(10)什么是BIOS
ubuntu·计算机基础
岁月玲珑15 小时前
【如何判断Linux系统是Ubuntu还是CentOS】
linux·ubuntu·centos
Kevin不想说话9261916 小时前
Ubuntu 24.04 安装搜狗输入法完整教程
ubuntu
矩阵老炮20 小时前
Ubuntu20.4编译AOSP源码实践
ubuntu·aosp