如何为系统输出着色?TL;DRANSI 转义序列有关 ANSI 转义序列的更多信息诅咒

2022-08-31 08:21:35

如何为 Java 输出着色?

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

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

答案 1

注意

你可能无法为 Window 着色,但它应该可以在许多 unix(或类似 unix)的终端中工作。cmd prompt

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

用法

请参阅底部的诅咒部分以获取最佳解决方案。有关个人或简单的解决方案(尽管不是跨平台解决方案),请参阅 ANSI 转义序列部分。


TL;DR

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

  • 蟒蛇print(chr(27) + "[31m" + "ERROR MESSAGE IN RED")

  • bashzshprintf '\x1b[31mERROR MESSAGE IN RED'
    • 这可能也适用于操作系统X:printf '\e[31mERROR MESSAGE IN RED'
  • sh: +,printf 'CTRLVCTRL+[[31mERROR MESSAGE IN RED'
    • 即,按 CTRL+V,然后按 CTRL+[ 以便在转义解释不可用时获取“原始”字符ESC
    • 如果操作正确,您应该会看到 .虽然它看起来像两个角色,但它实际上只是一个,角色。^[ESC
    • 您还可以在任何编程或 sripting 语言的 vim 中按 +,+ ,因为这会使用文字字符CTRLVCTRL[ESC
    • 另外,您可以将+替换为...例如,您可以使用+,,但我发现前者更容易,因为我已经在按了,并且由于不太出路。Ctrl[ESCCTRLVESCCTRL[

ANSI 转义序列

转义序列的背景

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

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

ANSI 转义序列的回溯

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

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

如何使用 ANSI 转义序列

一般

  • 转义序列以转义字符开头;对于 ANSI 转义序列,序列始终以 (ASCII: / 十六进制: ) 开头。ESC270x1B
  • 有关您可以执行的操作的列表,请参阅维基百科上的ANSI转义序列列表

在编程语言中

一些编程语言(如Java)不会解释或作为字符。但是,我们知道 ASCII 字符字符,因此我们可以简单地将类型转换为 a,然后使用它来开始转义序列。\e\x1bESC27ESC27char

以下是在常见编程语言中执行此操作的一些方法:

  • 爪哇岛

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

    • print(chr(27) + "[34mBLUE");
    • print("\x1b[35mMAGENTA");
      • 请注意,在python中可以正确解释\x1b
  • 节点 JS

    • 以下内容不会在 Web 控制台的 JavaScript 中为输出着色
    • console.log(String.fromCharCode(27) + "[36mCYAN");
    • console.log("\x1b[30;47mBLACK_ON_WHITE");
      • 请注意,也适用于节点\x1b

在外壳提示符 OR 脚本中

如果您使用的是 bashzsh,则很容易为输出着色(在大多数终端中)。在 Linux、Os X 和某些 Window 的终端中,您可以通过执行以下两项操作来检查您的终端是否支持颜色:

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

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

如果我没记错的话,linux终端倾向于同时支持和转义序列,而os x终端只倾向于支持,但我可能是错的。尽管如此,如果您看到如下图所示的内容,那么您就一切就绪了!(请注意,我使用的是 shell zsh,它正在为我的提示字符串着色;此外,我在 linux 中使用 urxvt 作为我的终端。\e\x1b\e

ANSI Escape Sequences Coloring Text Red

“这是怎么回事?”你可能会问。Bascially, 是解释后面的字符序列(单引号内的所有内容)。当遇到 或 时,它会将这些字符转换为字符 (ASCII: 27)。这正是我们想要的。现在,发送 ,并且由于后面跟着一个有效的ANSI转义序列,我们应该获得彩色输出(只要终端支持它)。printfprintf\e\x1bESCprintfESC31mESC

您还可以使用(例如)为输出着色。请注意,“[启用] 反斜杠转义的解释”的标志,如果要适当地解释转义序列,则必须使用该标志。echo -e '\e[32mGREEN'-eechoecho


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

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

在维基百科上,他们称之为,所以我也会这样做。ESC[CSI

颜色

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

  • CSI n m
    • CSI:转义字符 — 或^[[ESC[
    • n:一个数字 - 以下之一:
      • 30-37, : 前景39
      • 40-47, : 背景49
    • m:文字 ASCII —终止转义序列m

我将使用 bash 或 zsh 来演示所有可能的颜色组合。在 bash 或 zsh 中翻扫以下内容,以便亲自查看(您可能需要替换为):\e\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;

结果:

使用 ANSI 转义的各种前景/背景颜色

快速参考(彩色)

+~~~~~~+~~~~~~+~~~~~~~~~~~+
|  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:转义字符 — 或^[[ESC[
    • n:一个数字 - 以下之一:
      • 0:重置
      • 1-9:打开各种文本效果
      • 21-29:关闭各种文本效果(支持少于1-9)
      • 30-37, : 前景色39
      • 40-47, : 背景颜色49
      • 38:8 位或 24 位前景色(请参阅下面的 8/24 位颜色
      • 48:8 位或 24 位背景色(请参阅下面的 8/24 位颜色
    • m:文字 ASCII —终止转义序列m

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

同样值得注意的是,您可以使用分号分隔上述任何属性。例如,将在 上显示 a,并且它将是 和 。printf '\e[34;47;1;3mCRAZY TEXT\n'CRAZY TEXTblue foregroundwhite backgroundbolditalic

例如:

字符串属性组合在一起示例屏幕截图

在 bash 或 zsh shell 中翻扫以下内容,以查看您可以执行的所有文本效果。(您可能需要替换为 .)\e\x1b

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

结果:

SGR state 1 SGR state 2

您可以看到我的终端支持除微弱(2),隐藏(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 位颜色

虽然大多数终端都支持此功能,但它的支持程度低于 , colors。0-79

语法:

  • CSI 38;5; n m
    • CSI:转义字符 — 或^[[ESC[
    • 38;5;:表示前景使用 8 位颜色的文本字符串
    • n:一个数字 - 以下之一:
      • 0-255

如果你想以一种很好的方式预览终端中的所有颜色,我有一个很好的脚本 gist.github.com

它看起来像这样:

8 位彩色示例屏幕截图

如果要使用 8 位颜色更改背景,只需将 替换为 :3848

  • CSI 48;5; n m
    • CSI:转义字符 — 或^[[ESC[
    • 48;5;:表示使用 8 位颜色作为背景的文本字符串
    • n:一个数字 - 以下之一:
      • 0-255

24 位颜色

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

vim 实际上支持 24 位颜色(请参阅 vim wiki 了解如何启用 24 位颜色)。它真的很整洁,因为它从为gvim定义的颜色方案中提取出来;例如,它使用fg / bg from作为24位颜色!尼托,是吧?highlight guibg=#______ guifg=#______

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

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

为了测试你可以拥有的众多颜色中的几种(或者我认为是可能性),你可以在bash或zsh中使用这个:(2^8)^32^2416777216

  • 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-terminal中,因为urxvt不支持24位颜色...把它放在一起,urxvt维护者...真实):

24 位彩色示例屏幕截图

如果您想要24位颜色作为背景...你猜对了!您只需替换为:3848

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

插入原始转义序列

有时并且不会起作用。例如,在sh shell中,有时两者都不起作用(尽管它现在在我的系统上确实如此,但我认为它以前不行)。\e\x1b

要避免这种情况,您可以使用 +,+ 或 ,CTRLVCTRL[CTRLVESC

这将插入一个“原始”字符 (ASCII: 27)。它看起来像这样,但不要担心;它只是一个字符,而不是两个。ESC^[

例如:

sh 原始转义字符示例屏幕截图


诅咒

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

在诅咒中启动和运行

我不会详细介绍,因为搜索引擎可以揭示网站的链接,这些网站可以比我更好地解释这一点,但我会在这里简要讨论它并给出一个例子。

为什么使用诅咒来代替ANSI逃脱?

如果您阅读上述文本,您可能会记得或有时会使用 。好吧,有时根本不起作用(这不是标准的,我从来没有使用过这样的终端,但这是可能的)。更重要的是,更复杂的转义序列(think和其他多字符键)很难支持每个终端(除非你愿意花费大量的时间和精力来解析 terminfo 和 termcap,并弄清楚如何处理每个终端)。\e\x1bprintf\e\x1bHome

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

大多数 curses 的实现都使用一个数据库来描述数千个不同终端的功能。有一些实现,如PDCurses,它们使用专门的设备驱动程序而不是终端数据库。大多数实现使用术语信息;有些人使用术语帽。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)

结果:

在此输入图像描述

你可能会认为这是一种更迂回的做事方式,但它真的是跨平台的(真的是跨终端......至少在类unix和类unix平台世界中)。对于颜色来说,它并不那么重要,但是当涉及到支持其他多序列转义序列(如,,,等)时,诅咒变得更加重要。HomeEndPage UpPage Down

使用 Tput 的示例

  • tput是用于操作光标和文本的命令行实用程序
  • tput随包装一起提供。如果要在终端中使用跨终端(ish)应用程序,则应使用tput,因为它解析terminfo或所需的任何内容,并使用一组标准化命令(如curses)并返回正确的转义序列。curses
  • 例:
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\!"

结果:

带 tput 的示例

有关 Tput 的更多信息


答案 2

这对我有用:

System.out.println((char)27 + "[31mThis text would show up red" + (char)27 + "[0m");

您需要结尾“[37m”才能将颜色恢复为白色(或您正在使用的任何内容)。如果你不这样做,它可能会使后面的所有内容都变为“红色”。