如何为 System.out.println 输出着色? [复制]

2023-12-14

如何为 Java 输出着色?

例如,在 C 和其他语言中,我可以使用 ANSI-escape,例如\033[0m去做这个。但在Java中它不起作用。

public static void main(String[] x) {
    System.out.println("\033[0m BLABLA \033[0m\n");
}

Note

您可能无法为 Windows 着色cmd prompt,但它应该可以在许多 UNIX(或类 Unix)终端中工作。

另请注意,某些终端根本不支持某些(如果有)ANSI 转义序列,尤其是 24 位颜色。

Usage

请参阅 部分Curses在底部寻找最佳解决方案。对于个人或简单的解决方案(尽管not作为跨平台解决方案),请参阅ANSI 转义序列部分。


TL;DR

  • java: System.out.println((char)27 + "[31m" + "ERROR MESSAGE IN RED");

  • python: print(chr(27) + "[31m" + "ERROR MESSAGE IN RED")

  • bash or zsh: printf '\x1b[31mERROR MESSAGE IN RED'
    • 这也可能适用于 Os X:printf '\e[31mERROR MESSAGE IN RED'
  • sh: printf 'CTRL+V,CTRL+[[31mERROR MESSAGE IN RED'
    • ie, press CTRL+V and then CTRL+[ in order to get a "raw" ESC character when escape interpretation is not available
    • If done correctly, you should see a ^[. Although it looks like two characters, it is really just one, the ESC character.
    • You can also press CTRL+V,CTRL+[ in vim in any of the programming or sripting langauges because that uses a literal ESC character
    • Also, you can replace Ctrl+[ with ESC … eg, you can use CTRL+V,ESC, but I find the former easier, since I am already pressing CTRL and since [ is less out of the way.

ANSI 转义序列

逃脱序列的背景

虽然这不是最好的方法,但在编程或脚本语言中执行此操作的最简单方法是使用转义序列。从该链接:

转义序列是用于更改计算机及其连接的外围设备状态的一系列字符。这些也称为控制序列,反映了它们在设备控制中的用途。

ANSI 转义序列的背景

然而,它比视频文本终端更容易,因为这些终端使用ANSI 转义序列。从该链接:

ANSI 转义序列是带内信令的标准,用于控制视频文本终端上的光标位置、颜色和其他选项。某些字节序列(大多数以 Esc 和“[”开头)嵌入到文本中,终端会查找这些字节并将其解释为命令,而不是字符代码。

如何使用 ANSI 转义序列

一般来说

  • Escape sequences begin with an escape character; for ANSI escape sequences, the sequence always begins with ESC (ASCII: 27 / hex: 0x1B).
  • 有关您可以执行的操作的列表,请参阅维基百科上的 ANSI 转义序列列表

在编程语言中

Some programming langauges (like Java) will not interpret \e or \x1b as the ESC character. However, we know that the ASCII character 27 is the ESC character, so we can simply typecast 27 to a char and use that to begin the escape sequence.

以下是使用常见编程语言实现此目的的一些方法:

  • Java

    • System.out.println((char)27 + "[33mYELLOW");
  • Python 3

    • print(chr(27) + "[34mBLUE");
    • print("\x1b[35mMAGENTA");
      • 注意\x1b在 python 中被正确解释
  • Node JS

    • 以下将NOTWeb 控制台中 JavaScript 的颜色输出
    • console.log(String.fromCharCode(27) + "[36mCYAN");
    • console.log("\x1b[30;47mBLACK_ON_WHITE");
      • 注意\x1b也适用于节点

在 Shell 提示符或脚本中

如果您正在与bash or zsh,对输出进行着色非常容易(在大多数终端中)。在 Linux、Os X 和某些 Window 终端中,您可以通过执行以下两项操作来检查终端是否支持颜色:

  • printf '\e[31mRED'
  • printf '\x1b[31mRED'

如果您看到两者的颜色,那就太好了!如果您只看到一种颜色,则使用该序列。如果您没有看到其中任何一个的颜色,请仔细检查以确保您输入的所有内容正确并且您使用的是 bash 或 zsh;如果您仍然看不到任何颜色,则您的终端可能不支持 ANSI 转义序列。

如果我没记错的话,linux 终端往往都支持\e and \x1b转义序列,而 os x 终端仅倾向于支持\e,但我可能是错的。尽管如此,如果您看到类似下图的内容,那么您就已经准备好了! (请注意,我使用的是 shell,zsh,它正在为我的提示字符串着色;另外,我正在使用urxvt作为我在 Linux 中的终端。)

ANSI Escape Sequences Coloring Text Red

"How does this work?" you might ask. Bascially, printf is interpretting the sequence of characters that follows (everything inside of the single-quotes). When printf encounters \e or \x1b, it will convert these characters to the ESC character (ASCII: 27). That's just what we want. Now, printf sends ESC31m, and since there is an ESC followed by a valid ANSI escape sequence, we should get colored output (so long as it is supported by the terminal).

您还可以使用echo -e '\e[32mGREEN'(例如),颜色输出。请注意,-e标记为echo “[启用]反斜杠转义的解释”如果你想要的话必须使用echo正确解释转义序列。


有关 ANSI 转义序列的更多信息

ANSI 转义序列不仅仅可以做颜色输出,但让我们从它开始,看看颜色到底是如何工作的;然后,我们将看到如何操作光标;最后,我们将看看如何使用 8 位颜色和 24 位颜色(尽管它的支持很薄弱)。

On Wikipedia, they refer to ESC[ as CSI, so I will do the same.

Color

要使用 ANSI 转义颜色输出,请使用以下命令:

  • CSI n m
    • CSI: escape character—^[[ or ESC[
    • n: a number—one of the following:
      • 30-37, 39:前景
      • 40-47, 49: 背景
    • m: ASCII 文字m—终止转义序列

我将使用 bash 或 zsh 来演示所有可能的颜色组合。将以下内容放入 bash 或 zsh 中亲自查看(您可能需要替换\e with \x1b):

  • for fg in {30..37} 39; do for bg in {40..47} 49; do printf "\e[${fg};${bg}m~TEST~"; done; printf "\n"; done;

Result:

various foreground/background colors using ANSI escapes

快速参考(颜色)

+~~~~~~+~~~~~~+~~~~~~~~~~~+
|  fg  |  bg  |  color    |
+~~~~~~+~~~~~~+~~~~~~~~~~~+
|  30  |  40  |  black    |
|  31  |  41  |  red      |
|  32  |  42  |  green    |
|  33  |  43  |  yellow   |
|  34  |  44  |  blue     |
|  35  |  45  |  magenta  |
|  36  |  46  |  cyan     |
|  37  |  47  |  white    |
|  39  |  49  |  default  |
+~~~~~~+~~~~~~+~~~~~~~~~~~+

选择图形呈现 (SGR)

SGR 只允许您更改文本。其中许多在某些终端中不起作用,因此在生产级项目中谨慎使用它们。但是,它们对于使程序输出更具可读性或帮助您区分不同类型的输出非常有用。

颜色实际上属于 SGR,因此语法是相同的:

  • CSI n m
    • CSI: escape character—^[[ or ESC[
    • n: a number—one of the following:
      • 0: reset
      • 1-9:开启各种文字效果
      • 21-29:关闭各种文本效果(支持较少1-9)
      • 30-37, 39: 前景色
      • 40-47, 49: 背景颜色
      • 38:8 位或 24 位前景色(请参见8/24 位颜色 below)
      • 48:8 位或 24 位背景颜色(请参阅8/24 位颜色 below)
    • m: ASCII 文字m—终止转义序列

尽管对微弱 (2)、斜体 (3)、下划线 (4)、闪烁 (5,6)、反白 (7)、隐藏 (8) 和划线 (9) 的支持很微弱,但有些(但很少全部)倾向于在 Linux 和 os x 终端上工作。

还值得注意的是,您可以用分号分隔上述任何属性。例如printf '\e[34;47;1;3mCRAZY TEXT\n'将会呈现CRAZY TEXT with a blue foreground on a white background,这将是bold and italic.

Eg:

string attributes together example screenshot

在 bash 或 zsh shell 中输入以下内容即可查看您可以执行的所有文本效果。 (您可能需要更换\e with \x1b.)

  • for i in {1..9}; do printf "\e[${i}m~TEST~\e[0m "; done

Result:

SGR state 1 SGR state 2

可以看到我的终端支持所有的文字效果except for faint (2), conceal(8) 和划掉 (9).

快速参考(SGR 属性 0-9)

+~~~~~+~~~~~~~~~~~~~~~~~~+
|  n  |  effect          |
+~~~~~+~~~~~~~~~~~~~~~~~~+
|  0  |  reset           |
|  1  |  bold            |
|  2  |  faint*          |
|  3  |  italic**        |
|  4  |  underline       |
|  5  |  slow blink      |
|  6  |  rapid blink*    |
|  7  |  inverse         |
|  8  |  conceal*        |
|  9  |  strikethrough*  |
+~~~~~+~~~~~~~~~~~~~~~~~~+

* not widely supported
** not widely supported and sometimes treated as inverse

8 位颜色

虽然大多数终端都支持这一点,但它的支持程度低于0-7,9 colors.

Syntax:

  • CSI 38;5; n m
    • CSI: escape character—^[[ or ESC[
    • 38;5;:表示使用 8 位颜色作为前景的文字字符串
    • n: a number—one of the following:
      • 0-255

如果您想以良好的方式预览终端中的所有颜色,我有gist.github.com 上有一个不错的脚本.

它看起来像这样:

8-bit color example screenshot

如果您想使用 8 位颜色更改背景,只需替换38 with a 48:

  • CSI 48;5; n m
    • CSI: escape character—^[[ or ESC[
    • 48;5;:表示使用 8 位颜色作为背景的文字字符串
    • n: a number—one of the following:
      • 0-255

24 位颜色

24 位颜色也称为真彩色,它提供了一些非常酷的功能。对这一点的支持肯定在增长(据我所知,它适用于大多数现代终端,​​除了urxvt,我的终端[插入愤怒的表情符号])。

vim 实际上支持 24 位颜色(请参阅vim wiki查看如何启用 24 位颜色)。它真的很简洁,因为它取自为 gvim 定义的颜色方案;例如,它使用来自的 fg/bghighlight guibg=#______ guifg=#______对于 24 位颜色!尼托,是吧?

以下是 24 位颜色的工作原理:

  • CSI 38;2; r ; g ; b m
    • CSI: escape character—^[[ or ESC[
    • 38;2;:表示使用 24 位颜色作为前景的文字字符串
    • r,g,b:数字——每个都应该是0-255

To test 一些您可以拥有多种颜色((2^8)^3 or 2^24 or 16777216我认为有可能),你可以在 bash 或 zsh 中使用它:

  • for r in 0 127 255; do for g in 0 127 255; do for b in 0 127 255; do printf "\e[38;2;${r};${g};${b}m($r,$g,$b)\e[0m "; done; printf "\n"; done; done;

结果(这是在gnome 终端 since urxvt不支持 24 位颜色...把它放在一起,urxvt 维护者...真正的):

24-bit color example screenshot

如果您想要 24 位颜色的背景......您猜对了!你只需更换38 with 48:

  • CSI 48;2; r ; g ; b m
    • CSI: escape character—^[[ or ESC[
    • 48;2;:表示使用 24 位颜色作为背景的文字字符串
    • r,g,b:数字——每个都应该是0-255

插入原始转义序列

有时\e and \x1b不管用。例如,在shshell,有时两者都不起作用(尽管它在我的系统上起作用)now,我不认为以前是这样)。

To circumvent this, you can use CTRL+V,CTRL+[ or CTRLV,ESC

This will insert a "raw" ESC character (ASCII: 27). It will look like this ^[, but do not fret; it is only one character—not two.

Eg:

sh raw escape char example screenshot


Curses

请参阅Curses(编程库)页面有关诅咒的完整参考。需要注意的是,curses 仅适用于 unix 和类 unix 操作系统。

使用 Curses 启动并运行

我不会讨论太多细节,因为搜索引擎可以显示网站的链接,这些网站可以比我更好地解释这一点,但我将在这里简要讨论并举一个例子。

为什么使用 Curses 而不是 ANSI 转义?

If you read the above text, you might recall that \e or \x1b will sometimes work with printf. Well, sometimes \e and \x1b will not work at all (this is not standard and I have never worked with a terminal like this, but it is possible). More importantly, more complex escape sequences (think Home and other multi-character keys) are difficult to support for every terminal (unless you are willing to spend a lot of time and effort parsing terminfo and termcap and and figuring out how to handle every terminal).

诅咒解决了这个问题。基本上,它能够使用这些方法了解终端具有哪些功能(如上面链接的维基百科文章所述):

Curses 的大多数实现都使用可以描述数千种不同终端功能的数据库。有一些实现,例如 PDCurses,它使用专门的设备驱动程序而不是终端数据库。大多数实现使用 terminfo;有些使用 termcap。 Curses 具有可向后移植到字符单元终端且简单的优点。对于不需要位图图形或多种字体的应用程序,使用curses 的界面实现通常比使用X 工具包的界面实现更简单、更快。

大多数时候,curses 会轮询 terminfo,然后能够了解如何操作光标和文本属性。然后,如果您需要所需的功能,您(程序员)可以使用 Curses 提供的 API 来操作光标或更改文本颜色或其他属性。

使用 Python 的示例

我发现 python 确实很容易使用,但如果你想在不同的编程语言中使用curses,那么只需在duckduckgo 或任何其他搜索引擎上搜索它即可。 :) 这是 python 3 中的一个简单示例:

import curses

def main(stdscr):
    # allow curses to use default foreground/background (39/49)
    curses.use_default_colors()

    # Clear screen
    stdscr.clear()

    curses.init_pair(1, curses.COLOR_RED, -1)
    curses.init_pair(2, curses.COLOR_GREEN, -1)
    stdscr.addstr("ERROR: I like tacos, but I don't have any.\n", curses.color_pair(1))
    stdscr.addstr("SUCCESS: I found some tacos.\n", curses.color_pair(2))

    stdscr.refresh() # make sure screen is refreshed
    stdscr.getkey()  # wait for user to press key

if __name__ == '__main__':
    curses.wrapper(main)

result:

enter image description here

You might think to yourself that this is a much more round-about way of doing things, but it really is much more cross-platform (really cross-terminal … at least in the unix- and unix-like-platform world). For colors, it is not quite as important, but when it comes to supporting other multi-sequence escape sequences (such as Home, End, Page Up, Page Down, etc), then curses becomes all the more important.

Tput 示例

  • tput是一个用于操作光标和文本的命令行实用程序
  • tput附带curses包裹。如果您想在终端中使用跨终端 (ish) 应用程序,您应该使用 tput,因为它会解析 terminfo 或它需要的任何内容,并使用一组标准化命令(如curses)并返回正确的转义序列。
  • example:
echo "$(tput setaf 1)$(tput bold)ERROR:$(tput sgr0)$(tput setaf 1) My tacos have gone missing"
echo "$(tput setaf 2)$(tput bold)SUCCESS:$(tput sgr0)$(tput setaf 2) Oh good\! I found my tacos\!"

Result:

example with tput

有关 Tput 的更多信息

  • see: http://linuxcommand.org/lc3_adv_tput.php看看 tput 是如何工作的
  • see: http://invisible-island.net/ncurses/man/terminfo.5.html查看可以使用的命令列表
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何为 System.out.println 输出着色? [复制] 的相关文章

随机推荐

  • 获取具有深层相关实体的对象

    假设我有一个具有一对一关系的实体类 如下所示 public class Transaction public int TransactionID get set public Double Amount get set public int
  • 通过 Carrierwave 和 Fog 上传文件时出现 Exconn::Errors::SocketError

    这是我最近遇到的问题的延续 堆栈级别太深错误 我认为是由强参数产生的 每当我做一个Post创建 其中涉及文件上传 我收到此错误 Started POST posts for 127 0 0 1 at 2014 08 28 08 47 09
  • 使用 Java 7 验证 OpenSSL 生成的 S/MIME 数字签名文件

    我们有一个流程 使用 OpenSSL 生成 S MIME 数字签名 稍后需要使用 Java 7 进行验证 一方面 我们使用 OpenSSL 读取文本文件并生成签名的数字输出 稍后进行验证 我们曾经使用 OpenSSL 进行验证 但现在我们需
  • 如何在 Jenkins 中 fork 一个后台进程?设置 BUILD_ID 并使用 nohup 似乎不起作用

    我在 Jenkins 版本 1 578 中有一份 Maven 工作 下面的 maven 代码片段 用 Groovy 代码编写的 Ant 脚本 启动了一个 Fuse 服务器 我无法让 Jenkins 在作业完成后让它继续运行
  • React hooks 重复的 React 包

    如上所述here 在react库中使用hooks时 经常会遇到react错误说hooks can only be called inside the body of a function component导致此错误的最可能原因是您的库链接
  • 将二进制数据(std::string)写入std::ofstream?

    我有一个std string包含我需要写入文件的二进制数据的对象 能ofstream f name f lt lt s 有什么问题吗 我需要完全按照原来的方式读回数据 我当然可以使用fwrite s c str s size 1 filep
  • 消除自动增量中的间隙

    假设我有一个带有自动递增 id 字段的 MySQL 表 然后我插入 3 行 然后 我删除第二行 现在表的 id 变为 1 3 我可以让 MySQL 纠正这个问题并将其设为 1 2 而无需编写程序吗 一旦创建了自动索引列 MySQL 就不允许
  • 将 MFMailComposeViewController 推送到导航堆栈上?不以模态方式呈现

    我有一个表格视图 在其中一个单元格中 它显示 联系人 选择此单元格后 我想推入 MFMailComposeViewController 我似乎只能以模态方式呈现这个 MFMailComposeViewController 这里有什么问题 T
  • 当视图大小依赖于多个子视图时指定的约束

    我正在使用自定义单元格UITableView 单元格中有 4 个视图 3UILabels and 1 UIImageView 灰色的 如下图所示 标签的文本是动态的 因此宽度和高度也是动态的 这里的宽度为UIImageView取决于2个标签
  • 如何使用控制台开发工具更新 Angular 4+ 表单值?

    我正在尝试使用控制台 开发工具 填写 Angular 4 表单 这就是我现在正在做的事情 function fillForm let el document querySelector input ng reflect name my in
  • 多个异步/等待链

    如何在 C 中进行多个 async await 链接 例如 启动几个 HTTP 请求 然后不等待所有请求 而是在每个请求完成后启动新请求 最简单的方法是编写一个async method async Task DownloadAndFollo
  • Pytorch几何稀疏邻接矩阵到边缘索引张量

    我的数据对象有data adj t参数 给我稀疏邻接矩阵 我怎样才能得到edge index大小张量 2 num edges 由此 正如你在docs 由于此功能仍处于实验阶段 一些操作 e g 图池方法 可能仍然需要您输入edge inde
  • 对动态数据透视列进行排序

    我有以下 SQL 查询 其中创建的列是无序的 我不太确定如何修复它 SELECT rhead rhcust AS Cust ID rdetl rdextp AS Inv Amt rhead rhivdt AS Inv Date INTO T
  • 测试java HBase连接

    我正在尝试使用 HBase Java API 将数据写入 HBase 我通过 Ambari 安装了 Hadoop HBase 以下是当前设置配置的方式 final Configuration CONFIGURATION HBaseConfi
  • 如何以编程方式安装 Android 应用程序而不提示,

    我正在尝试在没有提示的情况下以编程方式安装该应用程序 意味着安装应用程序时不会显示用户必须按下的弹出窗口install选项 我跟着THIS回答 但每当我运行代码时 它都会抛出错误 java io IOException 运行 exec 时出
  • 如何使用 Cloudformation 在 AWS WAF 中启用 WebACL 日志记录?

    我正在经历AWS WAF 云信息文档 我找不到启用日志记录的方法 我可以通过控制台启用日志记录 但我想通过 Cloudformation 来执行此操作 以便在新堆栈中默认启用它 如何通过 Cloudformation 在 AWS WAF W
  • MS Office 2007 文件的 PHP 5.3.5 fileinfo() MIME 类型 - magic.mime 更新?

    在 PHP 上传中 我尝试验证正在上传的文件的 MIME 类型 以匹配应用程序的一组有效的 MIME 类型 当尝试使用 fileinfo 确定 Office 2007 文件的 MIME 类型时 它没有检测到相应的 MIME 类型 相反 MI
  • 带 React Hooks 的可重用下拉菜单

    正如我从 React 文档中得到的那样 使用钩子不需要大量代码重构 并且可以轻松包含在现有代码中 我想制作可重用的下拉菜单 从反应组件渲染方法调用 这是我的代码 navigation js import DropdownToggler fr
  • Regex.Replace 拒绝用换行符替换

    您好 我编写了一个非常简单的 C 程序 从命令行使用 C Regex 而不是依赖于 MS Word 搜索和替换 问题是 即使正则表达式可以很好地识别 r 和 n 当我尝试用其中任何一个替换字符串时 它似乎用转义字符而不是字符本身替换它 ST
  • 如何为 System.out.println 输出着色? [复制]

    这个问题在这里已经有答案了 如何为 Java 输出着色 例如 在 C 和其他语言中 我可以使用 ANSI escape 例如 033 0m去做这个 但在Java中它不起作用 public static void main String x