如何为System.out.println输出颜色? [重复]

问题

这个问题在这里已有答案:

  • 如何使用System.out.println在控制台中打印颜色? 6个答案

如何为Java输出着色?

例如,在C语言和其他语言中,我可以使用ANSI-escape like\033[0m来执行此操作。但在Java中它不起作用。

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

#1 热门回答(79 赞)

注意

你可能无法为Window'scmd prompt着色,但它应该可以在许多unix(或unix-like)终端中使用。

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

###用法

请参阅底部的部分Curses以获得最佳解决方案。对于个人或简单的解决方案(虽然6​​68127912不是是跨平台解决方案),请参阅ANSI Escape Sequences**部分。

#TL; DR

  • java:System.out.println((char)27"[31m""ERROR MESSAGE IN RED");
  • python:print(chr(27)"[31m""ERROR MESSAGE IN RED")
  • bash或zsh:printf'\ x1b [31mERROR MESSAGE IN RED'这也适用于Os X:printf'\ e [31mERROR MESSAGE IN RED'
  • sh:printf'CTRL V,CTRL [[31mERROR MESSAGE IN RED'即,按CTRL V然后按CTRL [以便在转义解释不可用时获得"原始"ESC字符如果正确完成,你应该看到^ [虽然它看起来像两个字符,但它实际上只是一个ESC字符。你也可以按CTRL V,CTRL [在任何编程或sripting语言中的vim,因为它使用文字ESC字符另外,你可以用Ctrl替换Ctrl [例如,你可以使用CTRL V,ESC,但我找到了前者更容易,因为我已经按下了CTRL,因为[不太偏僻。

#ANSI转义序列

Escape序列背景

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

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

ANSI Escape序列的## Backgound

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

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

##如何使用ANSI转义序列

###一般

  • 转义序列以转义字符开头;对于ANSI转义序列,序列始终以ESC开头(ASCII:27 / hex:0x1B)。
  • 有关你可以执行的操作的列表,请参阅Wikipedia上的ANSI转义序列列表

###在编程语言中

一些编程语言(如Java)不会将\e\x1b解释为字符。但是,我们知道ASCII character27theCCcharacter,所以我们可以简单地将类型转换为27到achar并使用它来开始转义序列。

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

  • Java System.out.println((char)27"[33mYELLOW");
  • Python 3 print(chr(27)"[34mBLUE");打印( "\ X1B [35mMAGENTA");请注意\ x1b在python中正确解释
  • Node JS以下内容不会在Web控制台console.log(String.fromCharCode(27)"[36mCYAN")中用JavaScript输出颜色。的console.log( "\ X1B [30; 47mBLACK_ON_WHITE");请注意\ x1b也适用于节点

###在Shell提示符或脚本中

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

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

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

如果我没记错的话,linux终端往往支持\e\x1bescape序列,而os x终端只支持\e,但我可能错了。尽管如此,如果你看到类似下图的内容,那么你已经完成了所有设置! (注意我正在使用shell,zsh,它正在着色我的提示字符串;另外,我在linux中使用urxvtas我的终端。)

ANSI Escape Sequences Coloring Text Red

"这怎么工作?"你可能会问。基本上,printf解释了后面的字符序列(单引号内的所有内容)。当printfencounters\e\x1b时,它会将这些字符转换为字符(ASCII:27)。这正是我们想要的。现在,printfsendsESC31m,并且由于有一个有效的ANSI转义序列,所以我们应该得到彩色输出(只要终端支持它)。

你也可以使用echo -e '\e[32mGREEN'(例如)来颜色输出。请注意,如果你希望echo正确解释转义序列,则必须使用-eflag forecho"[enable]解释反斜杠转义"。

#更多关于ANSI Escape的信息序列

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

OnWikipedia,他们引用了ESP [asCSI,所以我也会这样做。

##颜色

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

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

我将使用bash或zsh来演示所有可能的颜色组合。在bash或zsh中将以下内容自行查看(你可能需要替换\ewith\x1b):

  • 对于fg {30..37} 39;在{40..47} 49为bg做;做printf"\ e [$ ; $ m~TEST~";完成; printf"\ n";完成;

结果:

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 nm 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终端上工作。

值得注意的是,你可以使用分号分隔上述任何属性。例如,printf '\e[34;47;1;3mCRAZY TEXT\n'将显示CRAZY TEXT,其中ablue foreground是awhite background,它将是bolditalic

例如:

string attributes together example screenshot

在bash或zsh shell中添加以下内容,以查看可以执行的所有文本效果。 (你可能需要更换\ewith\x1b。)

  • 对于我在{1..9};做printf"\ e [$ m~TEST~ \ e [0m"; DONE

结果:

SGR state 1

SGR state 2

你可以看到我的终端支持所有文本效果**,除了**forfaint(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位颜色

虽然大多数终端都支持此功能,但它的支持率低于0-7,9

句法:

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

如果你想以一种很好的方式预览终端中的所有颜色,我有a nice script on gist.github.com

它看起来像这样:

8-bit color example screenshot

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

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

24位颜色

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

vim实际上支持24位颜色(请参阅vim wiki以了解如何启用24位颜色)。它真的很整洁,因为它来自为gvim定义的colorscheme;例如,它使用14081555的fg / bg作为24位颜色! Neato,是吗?

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

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

为了测试你可以拥有的许多颜色中的一些颜色(我认为),你可以在bash或zsh中使用它:

  • 对于r在0 127 255;为0 127 255做g;对于0 127 255中的b; do printf"\ e [38; 2; $ ; $ ; $ m($ r,$ g,$ b)\ e [0m";完成; printf"\ n";完成;完成;

结果(这是ingnome-terminalsinceurxvtDOES NOT SUPPORT 24-bit color ...把​​它放在一起,urxvt维护者......真实的):

24-bit color example screenshot

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

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

##插入原始转义序列

有时\e\x1b将无法正常工作。例如,在theshshell中,有时两者都不起作用(虽然它在我的系统现在,我认为它不常用)。

为了避免这种情况,你可以使用CTRL V,CTRL [orCTRLV,ESC

这将插入一个"原始"ESC字符(ASCII:27)。它看起来像这个^[,但不要担心;它只有一个性格 - 不是两个。

例如:

sh raw escape char example screenshot

#Curses

有关curses的完整参考,请参阅Curses (Programming Library) page。应该注意的是,curses仅适用于unix和类Unix操作系统。

##启动并运行Curses

我不会详细介绍,因为搜索引擎可以显示可以解释这一点的网站链接,但我会在这里简要讨论并举例说明。

###为什么使用Curses而不是ANSI Escapes?

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

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

大多数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)

结果:

enter image description here

你可能会认为这是一种更为全面的处理方式,但实际上它更具跨平台性(实际上是跨终端的...至少在unix和unix-like-platform世界中)。对于颜色来说,它并不重要,但是当支持其他多序列转义序列(例如Home,End,Page Up,Page Down等)时,curses就变得更加重要了。

Tput示例

  • tput是一个用于操作游标和文本的命令行实用程序
  • tput附带了curses包。如果要在终端中使用跨终端(ish)应用程序,则应使用tput,因为它解析terminfo或其所需的任何内容并使用一组标准化命令(如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\!"

结果:

example with tput

###关于Tput的更多信息

  • 请参阅:http://linuxcommand.org/lc3_adv_tput.php,了解tput的工作原理
  • 请参阅:http://invisible-island.net/ncurses/man/terminfo.5.html以获取可以使用的命令列表

#2 热门回答(31 赞)

这对我有用:

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

你需要结尾"[37m"将颜色恢复为白色(或者你正在使用的任何颜色)。如果你不这样做,它可能会使一切跟随"红色"。


#3 热门回答(26 赞)

不,但有第三方API可以处理它
http://www.javaworld.com/javaworld/javaqa/2002-12/02-qa-1220-console.html
编辑:当然有比我发布的文章更新的文章,但信息仍然可行。