65.9K
CodeProject 正在变化。 阅读更多。
Home

如何在 Windows 终端中更改文本颜色

starIconstarIconstarIconstarIconstarIcon

5.00/5 (11投票s)

2022 年 4 月 7 日

CPOL

2分钟阅读

viewsIcon

21512

downloadIcon

382

快速概述和一个简单的 Windows CMD 脚本,让你的终端输出更生动

引言

默认的终端文本输出是单色的,并且没有提供简单的方法来提供上下文。 例如,您可能希望错误以红色显示,成功以绿色显示,或者重要信息以粗体输出。

向终端输出添加颜色非常简单,只需在文本之前输出正确的控制字符即可。

这是 如何在 Linux 终端中更改文本颜色 的配套文章。

终端颜色

要输出彩色文本,您需要 echo 所需颜色的控制字符,然后输出您的文本,然后(为了整洁)将输出重置回默认值。 下表列出了代码

Color Foreground 背景
默认值 ESC[39m ESC[49m
黑色 ESC[30m ESC[40m
深红色 ESC[31m ESC[41m
深绿色 ESC[32m ESC[42m
深黄色 (橙色) ESC[33m ESC[43m
深蓝色 ESC[34m ESC[44m
深品红色 ESC[35m ESC[45m
深青色 ESC[36m ESC[46m
浅灰色 ESC[37m ESC[47m
深灰色 ESC[90m ESC[100m
红色 ESC[91m ESC[101m
绿色 ESC[92m ESC[101m
橙色 ESC[93m ESC[103m
蓝色 ESC[94m ESC[104m
品红色 ESC[95m ESC[105m
青色 ESC[96m ESC[106m
白色 ESC[97m ESC[107m

重置代码是 ESC[0m,其中 ESC 是转义代码。

前景色字符串的格式为

"ESC[" + "<0 or 1, meaning normal or bold>;" + "<color code> + "m"

背景色字符串的格式为

"ESC[" + "<color code>" + "m"

这些代码可以一起输出,以便同时更改前景色和背景色。

Using the Code

在输出颜色代码之前,您需要生成 ESC 序列。 最简单的方法可能是先生成一次并将其存储起来以供以后使用

:: Sets up the ESC string for use later in this script
:setESC
    for /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (
      set ESC=%%b
      exit /B 0
    )
    exit /B 0

这将设置一个变量 ESC,其中包含正确的序列。

输出红色文本的简单示例

setlocal enabledelayedexpansion
call :setESC
echo !ESC![91mThis is red text!ESC![0m

在白色背景上输出红色文本的示例

setlocal enabledelayedexpansion
call :setESC
echo !ESC![91m!ESC![107mThis is red text on a white background!ESC![0m"

这有点麻烦,所以我创建了一些简单的子程序,这些子程序提供了以更文明的方式输出文本的方法。

辅助函数

以下辅助函数允许您执行以下操作

call :WriteLine "This is red text" "Red"
call :WriteLine "This is red text on a white background" "Red" "White"

容易多了。

REM  Set to false if you find your environment just doesn't handle colors well
set useColor=true


:: Sets up the ESC string for use later in this script
:setESC
    for /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (
      set ESC=%%b
      exit /B 0
    )
    exit /B 0

:: Sets the currentColor global for the given foreground/background colors
:: currentColor must be output to the terminal before outputting text in
:: order to generate a colored output.
::
:: string foreground color name. Optional if no background provided.
::        Defaults to "White"
:: string background color name.  Optional. Defaults to Black.
:setColor

    REM If you want to get a little fancy then you can also try
    REM  - %ESC%[4m - Underline
    REM  - %ESC%[7m - Inverse

    set foreground=%~1
    set background=%~2

    if "!foreground!"=="" set foreground=White
    if /i "!foreground!"=="Default" set foreground=White
    if "!background!"=="" set background=Black
    if /i "!background!"=="Default" set background=Black

    if "!ESC!"=="" call :setESC

    REM This requires the setContrastForeground subroutine, which is discussed below
    if /i "!foreground!"=="Contrast" (
        call :setContrastForeground !background!
        set foreground=!contrastForeground!
    )

    set currentColor=

    REM Foreground Colours
    if /i "!foreground!"=="Black"       set currentColor=!ESC![30m
    if /i "!foreground!"=="DarkRed"     set currentColor=!ESC![31m
    if /i "!foreground!"=="DarkGreen"   set currentColor=!ESC![32m
    if /i "!foreground!"=="DarkYellow"  set currentColor=!ESC![33m
    if /i "!foreground!"=="DarkBlue"    set currentColor=!ESC![34m
    if /i "!foreground!"=="DarkMagenta" set currentColor=!ESC![35m
    if /i "!foreground!"=="DarkCyan"    set currentColor=!ESC![36m
    if /i "!foreground!"=="Gray"        set currentColor=!ESC![37m
    if /i "!foreground!"=="DarkGray"    set currentColor=!ESC![90m
    if /i "!foreground!"=="Red"         set currentColor=!ESC![91m
    if /i "!foreground!"=="Green"       set currentColor=!ESC![92m
    if /i "!foreground!"=="Yellow"      set currentColor=!ESC![93m
    if /i "!foreground!"=="Blue"        set currentColor=!ESC![94m
    if /i "!foreground!"=="Magenta"     set currentColor=!ESC![95m
    if /i "!foreground!"=="Cyan"        set currentColor=!ESC![96m
    if /i "!foreground!"=="White"       set currentColor=!ESC![97m
    if "!currentColor!"=="" set currentColor=!ESC![97m
    
    if /i "!background!"=="Black"       set currentColor=!currentColor!!ESC![40m
    if /i "!background!"=="DarkRed"     set currentColor=!currentColor!!ESC![41m
    if /i "!background!"=="DarkGreen"   set currentColor=!currentColor!!ESC![42m
    if /i "!background!"=="DarkYellow"  set currentColor=!currentColor!!ESC![43m
    if /i "!background!"=="DarkBlue"    set currentColor=!currentColor!!ESC![44m
    if /i "!background!"=="DarkMagenta" set currentColor=!currentColor!!ESC![45m
    if /i "!background!"=="DarkCyan"    set currentColor=!currentColor!!ESC![46m
    if /i "!background!"=="Gray"        set currentColor=!currentColor!!ESC![47m
    if /i "!background!"=="DarkGray"    set currentColor=!currentColor!!ESC![100m
    if /i "!background!"=="Red"         set currentColor=!currentColor!!ESC![101m
    if /i "!background!"=="Green"       set currentColor=!currentColor!!ESC![102m
    if /i "!background!"=="Yellow"      set currentColor=!currentColor!!ESC![103m
    if /i "!background!"=="Blue"        set currentColor=!currentColor!!ESC![104m
    if /i "!background!"=="Magenta"     set currentColor=!currentColor!!ESC![105m
    if /i "!background!"=="Cyan"        set currentColor=!currentColor!!ESC![106m
    if /i "!background!"=="White"       set currentColor=!currentColor!!ESC![107m

    exit /B 0

:: Outputs a line, including linefeed, to the terminal using the given foreground / background
:: colors 
::
:: string The text to output. Optional if no foreground provided. Default is just a line feed.
:: string Foreground color name. Optional if no background provided. Defaults to "White"
:: string Background color name. Optional. Defaults to "Black"
:WriteLine
    SetLocal EnableDelayedExpansion
    
    if "!ESC!"=="" call :setESC    
    set resetColor=!ESC![0m

    set str=%~1

    if "!str!"=="" (
        echo:
        exit /b 0
    )
    if "!str: =!"=="" (
        echo:
        exit /b 0
    )

    if /i "%useColor%"=="true" (
        call :setColor %2 %3
        echo !currentColor!!str!!resetColor!
    ) else (
        echo !str!
    )
    exit /b 0

:: Outputs a line without a linefeed to the terminal using the given foreground / background colors 
::
:: string The text to output. Optional if no foreground provided. Default is just a line feed.
:: string Foreground color name. Optional if no background provided. Defaults to "White"
:: string Background color name. Optional. Defaults to "Black"
:Write
    SetLocal EnableDelayedExpansion
    
    if "!ESC!"=="" call :setESC
    set resetColor=!ESC![0m

    set str=%~1

    if "!str!"=="" exit /b 0
    if "!str: =!"=="" exit /b 0

    if /i "%useColor%"=="true" (
        call :setColor %2 %3
        <NUL set /p =!currentColor!!str!!resetColor!
    ) else (
        <NUL set /p =!str!
    )
    exit /b 0

处理对比度

假设我们定义了一组预定义的颜色,并且我们希望使用它们来确保一致性

set color_primary=Blue
set color_mute=Gray
set color_info=Yellow
set color_success=Green
set color_warn=DarkYellow
set color_error=Red

如果我们使用这些颜色作为背景色输出文本,我们会得到

call :WriteLine
call :WriteLine "Default color on predefined background"
call :WriteLine

call :WriteLine "  Default colored background" "Default"
call :WriteLine "  Primary colored background" "Default" %color_primary%
call :WriteLine "  Mute colored background"    "Default" %color_mute%
call :WriteLine "  Info colored background"    "Default" %color_info%
call :WriteLine "  Success colored background" "Default" %color_success%
call :WriteLine "  Warning colored background" "Default" %color_warn%
call :WriteLine "  Error colored background"   "Default" %color_error%

有些模糊,因此让我们添加一个函数,该函数将在我们选择的任何背景上提供对比鲜明的前景。

:: Sets the name of a color that will providing a contrasting foreground
:: color for the given background color.
::
:: string background color name. 
:: on return, contrastForeground will be set
:setContrastForeground

    set background=%~1

    if "!background!"=="" background=Black

    if /i "!background!"=="Black"       set contrastForeground=White
    if /i "!background!"=="DarkRed"     set contrastForeground=White
    if /i "!background!"=="DarkGreen"   set contrastForeground=White
    if /i "!background!"=="DarkYellow"  set contrastForeground=White
    if /i "!background!"=="DarkBlue"    set contrastForeground=White
    if /i "!background!"=="DarkMagenta" set contrastForeground=White
    if /i "!background!"=="DarkCyan"    set contrastForeground=White
    if /i "!background!"=="Gray"        set contrastForeground=Black
    if /i "!background!"=="DarkGray"    set contrastForeground=White
    if /i "!background!"=="Red"         set contrastForeground=White
    if /i "!background!"=="Green"       set contrastForeground=White
    if /i "!background!"=="Yellow"      set contrastForeground=Black
    if /i "!background!"=="Blue"        set contrastForeground=White
    if /i "!background!"=="Magenta"     set contrastForeground=White
    if /i "!background!"=="Cyan"        set contrastForeground=Black
    if /i "!background!"=="White"       set contrastForeground=Black

    exit /B 0

我们已经在 Write 方法中连接了它:如果前景色设置为“Contrast”,那么前景色将被设置为与给定背景具有良好对比度的颜色。

要使用,我们只需这样做

call :WriteLine "  Primary colored background" "Contrast" %color_primary%
call :WriteLine "  Mute colored background"    "Contrast" %color_mute%
call :WriteLine "  Info colored background"    "Contrast" %color_info%
call :WriteLine "  Success colored background" "Contrast" %color_success%
call :WriteLine "  Warning colored background" "Contrast" %color_warn%
call :WriteLine "  Error colored background"   "Contrast" %color_error%

有趣的要点

其中的一个挑战是在没有换行符的情况下通过 CMD shell 输出文本。 默认情况下,<var>echo</var> 命令会添加换行符。 要在不包含换行符的情况下在 CMD 脚本中输出文本,只需使用

<NUL set /p ="My string goes here"
© . All rights reserved.