【问题标题】:How to have multiple colors in a Windows batch file?如何在 Windows 批处理文件中有多种颜色?
【发布时间】:2011-05-19 09:16:58
【问题描述】:

我想知道是否可以在 Windows 批处理文件的同一行上使用不同颜色的文本,例如,如果它说

echo hi world

我希望“hi”是一种颜色,而“world”是另一种颜色。也许我可以将 COLOR 命令设置为变量:

set color1= color 2
set color9= color A

然后将它们与

一起部署在同一行
echo hi world

但我不知道该怎么做。

【问题讨论】:

    标签: windows batch-file colors character-encoding cmd


    【解决方案1】:

    我会先给你你想要的答案,给那些不想阅读一堆解释的人。

    使用ANSI_escape_code.SGR_parameters

    @echo off 
    echo [38;2;255;255;0mHi[m [38;2;128;128;255mWorld[m 
    pause > nul
    

    ?不要忘记输入ESC0x1B (Hex), \033 (Oct), 27(Dec)Virtual-Key Codes VK_ESCAPE

    我建议你将上面的内容复制(以防你缺少ESC键),然后将其粘贴到notepad++或其他你喜欢的IDE上。

    输出如下图

    说明

    ANSI_escape_code.SGR_parameters你知道

    Number Name Note Example
    0 Reset or normal All attributes off ESC[0m or ESC[m
    1 Bold or increased intensity ESC[1m
    3 Italic ESC[3m
    4 Underline ESC[4m
    8 Conceal or hide Not widely supported. ESC[8m
    30–37 Set foreground color 30:black 31: red, 32: green, 33: yellow, 34: blue, 35: purple, 36: Aqua, 37: white red: ESC[31m
    38 Set foreground color Next arguments are 5;n or 2;r;g;b red: ESC[38m;2;255;0;0m
    40–47 Set background color red: ESC[41m
    48 Set background color Next arguments are 5;n or 2;r;g;b red: ESC[48m;2;255;0;0m

    当然,还有很多你可以去看看。

    例如,

    Fake code code (copy this to try by yourself) demo
    ESC[31mESC[4mfore color: red and style:underlineESC[0m echo [31m[4mfore color: red and style:underline[0m
    ESC[31mESC[4mfore color: red and style:underlineESC[0m
      |       |                 |                   ------ ? Reset, such that the next one will not apply.
      |       |  -----------------------------------
      |       |  ? input message      
      |       |
      |    ------ 
      |    ? Underline
      |
    -------
    ? Set foreground color 31 is red
    

    其中 ESC = 0x1B(因为在这里输入 ESC,所以用户看不到它。)

    脚本和练习

    @echo off
    
    :: demo: foreground color
    for /l %%x in (30, 1, 37) do (
       call :demoDefaultColor "COLOR" %%x
    )
    
    :: demo: background color
    for /l %%x in (40, 1, 47) do (
       call :demoDefaultColor "COLOR" %%x
    )
    
    call :echoWithColor "Hello world!" 255 0 0
    echo Hello world!
    call :echoWithColor "Hello world!" 255 0 255  255 255 0
    
    pause > nul
    EXIT /B
    
    
    :demoDefaultColor <msg> <colorFlag>
        echo [%2m%~1[0m
        EXIT /B
    
    :echoWithColor <msg> <fr> <fg> <fb> <br> <bg> <bb>
        SET msg=%~1
        SET fr=%2
        SET fg=%3
        SET fb=%4
        SET br=%5
        SET bg=%6
        SET bb=%7
    
        echo [48;2;%br%;%bg%;%bb%m[38;2;%fr%;%fg%;%fb%m%msg%[0m
        EXIT /B
    

    输出:

    【讨论】:

    【解决方案2】:

    Windows 10 用户virtual terminal 代码使用的宏解决方案

    对于 Windows 10 用户来说,这是除了直接使用 VT 序列之外最快的方法,而且更具可读性。

    ::: Author T3RRY : Created 09/04/2021 : Version 1.0.7
    ::: Version changes:
    ::: - ADDED /A switch to allow absolute Y;X value to be supplied as a single switch subarg
    ::: - ADDED /@ switch to allow saving of cursor position. Subarg allows custom return var to store multiple positions.
    ::: - ADDED random subarg for /C color switch.
    ::: - ADDED optional companion switch to /C - '/B'
    :::  - When /C random subarg is used, /B may be used with any ONE of the following: R G B C M Y
    :::    to bias the output color towards Red Green Blue Cyan Magenta or Yellow
    ::: - ADDED support for switches with common prefix.
    ::: - ADDED /T timeout switch for subsecond delays
    ::: - CORRECTED Switch validation method to handle Switches at EOL with no subargs
    ::: - ADDED /E Switch to allow /C value to be preserved or Color to be changed at EOL with an integer subarg.
    ::: - Support REMOVED for switch usage pattern /Switch:value
    :::
    ::: Purpose      : Color and cursor position macro for windows 10 batch files
    ::: - Allows rapid display of colored output at specified screen position.
    :::   For more information, read the usage.
    :::
    ::: Uses macro parameter and switch handling template.
    :::  - See :  https://pastebin.com/gzL7AYpC
    
    @Echo off
    
    :# Windows Version control. Assigns flag true if system is windows 10.
     Set "Win10="
     Ver | Findstr /LIC:" 10." > nul && Set "Win10=true"
    
    :# Test if virtual terminal codes enabled ; enable if false
    :# removes win10 flag definition if version does not support Virtual Terminal sequences
     If defined Win10 (
      Reg Query HKCU\Console | %SystemRoot%\System32\findstr.exe /LIC:"VirtualTerminalLevel    REG_DWORD    0x1" > nul || (
        Reg Add HKCU\Console /f /v VirtualTerminalLevel /t REG_DWORD /d 1
      ) > Nul || Set "Win10="
     )
     If not defined Win10 (
      Echo(Virtual terminal sequences not supported on your system
      Exit /B 1
     )
    
     If "%~1" == "" (
      Mode 200,150
      Cls
     )
    
    :# /@ Switch requires clean working driectory to execute in.
     RD "%TEMP%\%~n0_Run" 2> nul && Timeout 1 > nul
     MD "%TEMP%\%~n0_Run"
    
    (Set \n=^^^
    
    %= \n macro newline variable. Do not modify =%)
    
    :# assign virtual terminal control character 0x27 'escape' variable \E
     For /F %%a in ( 'Echo prompt $E ^| cmd' )Do Set "\E=%%a"
    
    ::# usage: %$Cout% [/?] | [/Alt | /Main] [/H [-|+]] [/T Int] [/X Int | /L Int | /R Int]
    ::#                [/Y Int | /U Int | /D Int] [/K |/Del Int | /I Int] [/N] [/@ {Optional:ReturnVar}]
    ::#                [/C Int | /C Int,Int | /C Int;Int | /C random] [/S "String"] [/E {Optional:0|Int}]
    ::# -----------------------------------------------------------------------------------------------------
    ::# Available Switches     : Description:
    ::# -----------------------------------------------------------------------------------------------------
    ::# /?                     : This help screen
    ::#
    ::# /S String              : String to be output. Tested for strings of 500 characters.
    ::# /S String{Substituion} : The following characters must be substituted for output:
    ::# /S ^!Variable:/={FS}^! : {AS}:* {DQ}:" {FS}:/ {EQ}:=
    ::#
    ::# /C Integer             : Declare output color using VT sequence
    ::# /C Integer,Integer     : Chain   mulitple VT color sequences
    ::# /C Integer;Integer     : Combine multiple VT values into the one sequence
    ::# /C random              : Random RGB foreground color
    ::# /B R|G|B|C|M|Y         : Bias /C random color toward Red Green Blue
    ::#                        : Cyan Magenta or Yellow. /C random must be used.
    ::# /E                     : Preserves /C Color value until /E 0 is used. /C must be used.
    ::# /E 0                   : Restores color to Black BG White FG after string output.
    ::# /E Integer             : Change color after string output to supplied value.
    ::#
    ::# /A Integer;Integer     : Move cursor to Line;Column    [ absolute   ]
    ::# /Y Integer             : Move cursor to Line Integer   [ absolute Y ]
    ::# /X Integer             : Move cursor to Column Integer [ absolute X ]
    ::# /U Integer             : Move cursor Up by Integer
    ::# /D Integer             : Move cursor Down by Integer
    ::# /R Integer             : Move cursor Right by Integer
    ::# /L Integer             : Move cursor Left by Integer
    ::#
    ::# /H -                   : Hide the cursor  : Note - If Cursor state is changed during a code block
    ::#                          redirected to a file, it cannot be changed again except within a code block.
    ::# /H +                   : Show the cursor
    ::# /Alt                   : Switch to alternate   buffer [ main buffer is preserved ]
    ::# /Main                  : Return to main screen buffer [ alternate buffer is cleared ]
    ::# /K                     : Clears text to right of current cursor position
    ::# /Del Integer           : Deletes Integer columns right of the cursor, shifting existing text left
    ::# /I Integer             : Inserts whitespace into Integer columns right of Cursor, shifting text right
    ::# /N                     : Output a newline after other switches are executed.
    ::# /T Integer             : Subsecond Delay after output. 25000 = ~1 Second [ Depending on clockspeed ]
    ::#
    ::# /@                     : Stores cursor position after execution in variables: $Cout{Y} , $Cout{X}
    ::#                        : and $Cout{pos} ( VT format 'IntY;IntX' )
    ::# /@ String-ReturnVar    : Return values to ReturnVar{pos} ReturnVar{Y} ReturnVar{X}
    ::#                    *!* : This switch MUST NOT be used during codeblocks that redirect output
    ::#                        : Slow execution time. ~ 17x slower than typical $Cout expansion
    ::#                        : 12/100th's vs 0.7/100th's of a second [with a clockspeed of 2904]
    ::#
    ::#                                               Notes:
    ::# - $Cout Macro does not support Concatenation of Expansions.
    ::# - No error validation is performed on switch Integer subargs. Invalid Virtual Terminal sequences
    ::#   will be disregarded and output as a string.
    ::#
    ::# Virtual Terminal sequence resource:
    ::# https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
    ::# -----------------------------------------------------------------------------------------------------
    
     Set $Cout_Switches="A" "Y" "X" "U" "D" "R" "L" "H" "Alt" "Main" "K" "Del" "I" "N" "T" "B" "C" "E" "S" "@"
    
     Set $Cout=For %%n in (1 2)Do if %%n==2 (%\n%
      For %%G in ( %$Cout_Switches% )Do Set "$Cout_Switch[%%~G]="%\n%
      Set "$Cout_leading.args=!$Cout_args:*/=!"%\n%
      For /F "Delims=" %%G in ("!$Cout_leading.args!")Do Set "$Cout_leading.args=!$Cout_args:/%%G=!"%\n%
      Set ^"$Cout_args=!$Cout_args:"=!"%\n%
      Set "$Cout_i.arg=0"%\n%
      For %%G in (!$Cout_leading.args!)Do (%\n%
       Set /A "$Cout_i.arg+=1"%\n%
       Set "$Cout_arg[!$Cout_i.arg!]=%%~G"%\n%
      )%\n%
      If "!$Cout_Args:~-2,1!" == "/" (%\n%
       Set "$Cout_Switch[!$Cout_Args:~-1!]=true"%\n%
       If not "!$Cout_Args:/?=!." == "!$Cout_Args!." Set "$Cout_Switch[help]=true"%\n%
       Set "$Cout_Args=!$Cout_Args:~0,-2!"%\n%
      )%\n%
      For %%G in ( %$Cout_Switches% )Do If not "!$Cout_args:/%%~G =!" == "!$Cout_args!" (%\n%
       Set "$Cout_Switch[%%~G]=!$Cout_Args:*/%%~G =!"%\n%
       If not "!$Cout_Switch[%%~G]:*/=!" == "!$Cout_Switch[%%~G]!" (%\n%
        Set "$Cout_Trail[%%~G]=!$Cout_Switch[%%~G]:*/=!"%\n%
        For %%v in ("!$Cout_Trail[%%~G]!")Do (%\n%
         Set "$Cout_Switch[%%~G]=!$Cout_Switch[%%~G]: /%%~v=!"%\n%
         Set "$Cout_Switch[%%~G]=!$Cout_Switch[%%~G]:/%%~v=!"%\n%
        )%\n%
        Set "$Cout_Trail[%%~G]="%\n%
        If "!$Cout_Switch[%%~G]:~-1!" == " " Set "$Cout_Switch[%%~G]=!$Cout_Switch[%%~G]:~0,-1!"%\n%
        If "!$Cout_Switch[%%~G]!" == "" Set "$Cout_Switch[%%~G]=true"%\n%
       )%\n%
      )%\n%
      If /I "!$Cout_Switch[C]!" == "random" (%\n%
       If not "!$Cout_Switch[B]!" == ""   (Set "$Cout_MOD=100")Else Set "$Cout_MOD=200"%\n%
       Set /A "$Cout_RR=!random! %% !$Cout_MOD! + 50,$Cout_GG=!random! %% !$Cout_MOD! + 50,$Cout_BB=!random! %% !$Cout_MOD! + 50"%\n%
       If /I "!$Cout_Switch[B]!" == "R" Set "$Cout_RR=250"%\n%
       If /I "!$Cout_Switch[B]!" == "G" Set "$Cout_GG=250"%\n%
       If /I "!$Cout_Switch[B]!" == "B" Set "$Cout_BB=250"%\n%
       If /I "!$Cout_Switch[B]!" == "M" Set /A "$Cout_RR=!Random! %% 50 + 200,Cout_GG=0,$Cout_BB=!Random! %% 50 + 200"%\n%
       If /I "!$Cout_Switch[B]!" == "Y" Set /A "$Cout_RR=!Random! %% 90 + 100,Cout_GG=!Random! %% 90 + 90,$Cout_BB=0"%\n%
       If /I "!$Cout_Switch[B]!" == "C" Set /A "$Cout_RR=0,Cout_GG=!Random! %% 120 + 30,$Cout_BB=175"%\n%
       Set "$Cout_Switch[C]=38;2;!$Cout_RR!;!$Cout_GG!;!$Cout_BB!"%\n%
      )%\n%
      If "!$Cout_Switch[help]!" == "true" ((For /F "Tokens=1,2 Delims=#" %%Y in ('findstr /BLIC:"::#" "%~f0"')Do @Echo(%%Z)^| @More)%\n%
      If not "!$Cout_Switch[C]!" == ""    (Set "$Cout_Color=%\E%[!$Cout_Switch[C]:,=m%\E%[!m")Else Set "$Cout_Color="%\n%
      If not "!$Cout_Switch[Y]!" == ""    (Set "$Cout_Ypos=%\E%[!$Cout_Switch[Y]!d")Else Set "$Cout_Ypos="%\n%
      If not "!$Cout_Switch[X]!" == ""    (Set "$Cout_Xpos=%\E%[!$Cout_Switch[X]!G")Else Set "$Cout_Xpos="%\n%
      For %%d in (U D L R)Do if not "!$Cout_Switch[%%d]!" == "" (Set /A "$Cout_Switch[%%d]=!$Cout_Switch[%%d]!")%\n%
      If not "!$Cout_Switch[U]!" == ""    (Set "$Cout_Yoffset=%\E%[!$Cout_Switch[U]!A")Else Set "$Cout_Yoffset="%\n%
      If not "!$Cout_Switch[D]!" == ""    Set "$Cout_Yoffset=%\E%[!$Cout_Switch[D]!B"%\n%
      If not "!$Cout_Switch[R]!" == ""    (Set "$Cout_Xoffset=%\E%[!$Cout_Switch[R]!C")Else Set "$Cout_Xoffset="%\n%
      If not "!$Cout_Switch[L]!" == ""    Set "$Cout_Xoffset=%\E%[!$Cout_Switch[L]!D"%\n%
      If "!$Cout_Switch[H]!" == "-"       Set "$Cout_Cursor=%\E%[?25l"%\n%
      If "!$Cout_Switch[H]!" == "+"       Set "$Cout_Cursor=%\E%[?25h"%\n%
      If "!$Cout_Switch[Main]!" == "true" (Set "$Cout_Buffer=%\E%[?1049l")Else Set "$Cout_Buffer="%\n%
      If "!$Cout_Switch[Alt]!" == "true"  Set "$Cout_Buffer=%\E%[?1049h"%\n%
      If not "!$Cout_Switch[A]!" == ""    (Set "$Cout_Absolutepos=%\E%[!$Cout_Switch[A]!H")Else Set "$Cout_Absolutepos="%\n%
      If not "!$Cout_Switch[K]!" == ""    (Set "$Cout_LineClear=%\E%[K")Else Set "$Cout_LineClear="%\n%
      If not "!$Cout_Switch[Del]!" == ""  (Set "$Cout_Delete=%\E%[!$Cout_Switch[Del]!P")Else Set "$Cout_Delete="%\n%
      If not "!$Cout_Switch[I]!" == ""    (Set "$Cout_Insert=%\E%[!$Cout_Switch[I]!@")Else Set "$Cout_Insert="%\n%
      If not "!$Cout_Switch[S]!" == ""    (%\n%
       Set "$Cout_String=!$Cout_Switch[S]:{FS}=/!"%\n%
       Set "$Cout_String=!$Cout_String:{EQ}==!"%\n%
       Set "$Cout_String=!$Cout_String:{AS}=*!"%\n%
       Set ^"$Cout_String=!$Cout_String:{DQ}="!"%\n%
      )Else (Set "$Cout_String=")%\n%
      If "!$Cout_Switch[E]!" == "true"    (Set "$Cout_EOLC=!$Cout_Color!")%\n%
      If not "!$Cout_Switch[E]!" == ""    (Set "$Cout_EOLC=%\E%[!$Cout_Switch[E]!m")%\n%
      If "!$Cout_EOLC!" == ""             (Set "$Cout_EOLC=%\E%[0m")%\n%
      ^< nul set /P "=!$Cout_Buffer!!$Cout_Cursor!!$Cout_Absolutepos!!$Cout_Ypos!!$Cout_YOffset!!$Cout_Xpos!!$Cout_XOffset!!$Cout_Delete!!$Cout_Insert!!$Cout_Color!!$Cout_LineClear!!$Cout_String!!$COUT_EOLC!"%\n%
      If "!$Cout_Switch[N]!" == "true"    Echo(%\n%
      If not "!$Cout_Switch[T]!" == ""    (For /L %%T in (1 1 !$Cout_Switch[T]!)Do (Call )%= Delay resetting Errorlevel to 0 =%)%\n%
      If "!$Cout_Switch[help]!" == "true" Pause%\n%
      If not "!$Cout_Switch[@]!" == "" (%\n%
       PUSHD "%TEMP%\%~n0_Run"%\n%
       Set "$Cout{pos}=" ^&Set "$Cout[Char]="%\n%
       For /L %%l in (2 1 12)Do (%\n%
        If not "!$Cout[Char]!" == "R" (%\n%
         ^<nul set /p "=%\E%[6n" %\n%
         FOR /L %%z in (1 1 %%l) DO pause ^< CON ^> NUL%\n%
         Set "$Cout[Char]=;"%\n%
         for /F "tokens=1 skip=1 delims=*" %%C in ('"REPLACE /W ? . < con"') DO (Set "$Cout[Char]=%%C")%\n%
         If "!$Cout{pos}!" == "" (Set "$Cout{pos}=!$Cout[Char]!")Else (set "$Cout{pos}=!$Cout{pos}!!$Cout[Char]:R=!")%\n%
       ))%\n%
       For /F "tokens=1,2 Delims=;" %%X in ("!$Cout{pos}!")Do Set "$Cout{Y}=%%X" ^& Set "$Cout{X}=%%Y" %\n%
       If not "!$Cout_Switch[@]!" == "true" (%\n%
        Set "{Pos}!$Cout_Switch[@]!=!$Cout{pos}!"%\n%
        Set /A "{Y}!$Cout_Switch[@]!=$Cout{Y},{X}!$Cout_Switch[@]!=$Cout{X}"%\n%
       )%\n%
       POPD "%TEMP%\%~n0_Run"%\n%
      )%\n%
     ) Else Set $Cout_args=
    
    :# enable macro
    Setlocal EnableExtensions EnableDelayedExpansion
    
    :# facilitate testing of the macro using parameters from the command line; or Call %~n0.bat /? to see help.
    
     if not "%~1" == ""  (
      %$Cout% %*
      Exit /B !Errorlevel!
     )
    
    :# usage example Ascii art ; Bird with animation
    
    :# ensures Y;X axis at screen home
    %$Cout% /A 1;1
    
    (
    %$Cout% /H - /C 1,33 /S "                ,      .-;" /N
    %$Cout% /C 1,33 /S "             ,  |\    {FS} {FS}  __," /N
    %$Cout% /C 1,33 /S "             |\ '.`-.|  |.'.-'" /N
    %$Cout% /C 1,33 /S "              \`'-:  `; : {FS}" /N
    %$Cout% /C 1,33 /S "               `-._'.  \'|" /N
    %$Cout% /C 1,33 /S "              ,_.-` ` `  ~,_" /N
    %$Cout% /C 1,33 /S "               '--,.    "
    %$Cout% /C 31 /S ".-. "
    %$Cout% /C 1,33 /S ",{EQ}{DQ}{EQ}." /N
    %$Cout% /C 1,33 /S "                 {FS}     "
    %$Cout% /C 31 /S "{ "
    %$Cout% /C 1,36 /S "} "
    %$Cout% /C 31 /S ")"
    %$Cout% /C 1,33 /S "`"
    %$Cout% /C 33 /S ";-."
    %$Cout% /C 1,33 /S "}" /N
    %$Cout% /C 1,33 /S "                 |      "
    %$Cout% /C 31 /S "'-' "
    %$Cout% /C 33 /S "{FS}__ |" /N
    %$Cout% /C 1,33 /S "                 {FS}          "
    %$Cout% /C 33 /S "\_,\|" /N
    %$Cout% /C 1,33 /S "                 |          (" /N
    %$Cout% /C 1,33 /S "             "
    %$Cout% /C 31 /S "__ "
    %$Cout% /C 1,33 /S "{FS} '          \" /N
    %$Cout% /C random /B G /S "     {FS}\_    "
    %$Cout% /C 31 /S "{FS},'`"
    %$Cout% /C 1,33 /S "|     '   "
    %$Cout% /C 31 /S ".-~^~~-." /N
    %$Cout% /C random /B G /S "     |`.\_ "
    %$Cout% /C 31 /S "|   "
    %$Cout% /C 1,33 /S "{FS}  ' ,    "
    %$Cout% /C 31 /S "{FS}        \" /N
    %$Cout% /C random /B G /S "   _{FS}  `, \"
    %$Cout% /C 31 /S "|  "
    %$Cout% /C 1,33 /S "; ,     . "
    %$Cout% /C 31 /S "|  ,  '  . |" /N
    %$Cout% /C random /B G /S "   \   `,  "
    %$Cout% /C 31 /S "|  "
    %$Cout% /C 1,33 /S "|  ,  ,   "
    %$Cout% /C 31 /S "|  :  ;  : |" /N
    %$Cout% /C random /B G /S "   _\  `,  "
    %$Cout% /C 31 /S "\  "
    %$Cout% /C 1,33 /S "|.     ,  "
    %$Cout% /C 31 /S "|  |  |  | |" /N
    %$Cout% /C random /B G /S "   \`  `.   "
    %$Cout% /C 31 /S "\ "
    %$Cout% /C 1,33 /S "|   '     "
    %$Cout% /C 1,32 /S "|"
    %$Cout% /C 31 /S "\_|-'|_,'\|" /N
    %$Cout% /C random /B G /S "   _\   `,   "
    %$Cout% /C 1,32 /S "`"
    %$Cout% /C 1,33 /S "\  '  . ' "
    %$Cout% /C 1,32 /S "| |  | |  |           "
    %$Cout% /C random /B G /S "__" /N
    %$Cout% /C random /B G /S "   \     `,   "
    %$Cout% /C 33 /S "| ,  '    "
    %$Cout% /C 1,32 /S "|_{FS}'-|_\_{FS}     "
    %$Cout% /C random /B G /S "__ ,-;` {FS}" /N
    %$Cout% /C random /B G /S "    \    `,    "
    %$Cout% /C 33 /S "\ .  , ' .| | | | |   "
    %$Cout% /C random /B G /S "_{FS}' ` _-`|" /N
    %$Cout% /C random /B G /S "     `\    `,   "
    %$Cout% /C 33 /S "\     ,  | | | | |"
    %$Cout% /C random /B G /S "_{FS}'   .{EQ}{DQ}  {FS}" /N
    %$Cout% /C random /B G /S "     \`     `,   "
    %$Cout% /C 33 /S "`\      \{FS}|,| ;"
    %$Cout% /C random /B G /S "{FS}'   .{EQ}{DQ}    |" /N
    %$Cout% /C random /B G /S "      \      `,    "
    %$Cout% /C 33 /S "`\' ,  | ; "
    %$Cout% /C random /B G /S "{FS}'    {EQ}{DQ}    _{FS}" /N
    %$Cout% /C random /B G /S "       `\     `,  "
    %$Cout% /C random /B M /S ".{EQ}{DQ}-. "
    %$Cout% /C 1,33 /S "': "
    %$Cout% /C random /B G /S "{FS}'     {EQ}{DQ}    .{FS}" /N
    %$Cout% /C random /B G /S "    jgs _`\    ;"
    %$Cout% /C random /B M /S "_{  '   ; "
    %$Cout% /C random /B G /S "{FS}'    {EQ}{DQ}      {FS}" /N
    %$Cout% /C random /B G /S "       _\`-{FS}__"
    %$Cout% /C random /B M /S ".~  `."
    %$Cout% /C 1,35,7,48;2;130;100;0 /S "8"
    %$Cout% /C random /B M /S ".'.^`~-. "
    %$Cout% /C random /B G /S "{EQ}{DQ}     _,{FS}" /N
    %$Cout% /C random /B G /S "    __\      "
    %$Cout% /C random /B M /S "{   '-."
    %$Cout% /C 1,35,7,48;2;150;130;0 /S "|"
    %$Cout% /C random /B M /S ".'.--~'`}"
    %$Cout% /C random /B G /S "     _{FS}" /N
    %$Cout% /C random /B G /S "    \    .{EQ}{DQ}` "
    %$Cout% /C random /B M /S "}.-~^'"
    %$Cout% /C 1,35,7,48;2;170;150;0 /S "@"
    %$Cout% /C random /B M /S "'-. '-..'  "
    %$Cout% /C random /B G /S "__{FS}" /N
    %$Cout% /C random /B G /S "   _{FS}  .{DQ}    "
    %$Cout% /C random /B M /S "{  -'.~('-._,.'"
    %$Cout% /C random /B G /S "\_,{FS}" /N
    %$Cout% /C random /B G /S "  {FS}  .{DQ}    _{FS}'"
    %$Cout% /C random /B M /S "`--; ;  `.  ;" /N
    %$Cout% /C random /B G /S "   .{EQ}{DQ}   _{FS}'      "
    %$Cout% /C random /B M /S "`-..__,-'" /N
    %$Cout% /C random /B G /S "     __{FS}'" /N
    ) > "%~dp0parrot.brd"
    TYPE "%~dp0parrot.brd"
    DEL "%~dp0parrot.brd"
    
    :# Just a bit of animation
    For /L %%i in (0 1 25)Do (
     %$Cout% /Y 25 /X 19 /C random /B M /S ".{EQ}{DQ}-. "
     %$Cout% /D 1 /X 17 /C random /B M /S "_{  '   ; "
     %$Cout% /D 1 /X 15 /C random /B M /S ".~  `."
     %$Cout% /R 1 /C random /B M /S ".'.^`~-. "
     %$Cout% /D 1 /X 14 /C random /B M /S "{   '-."
     %$Cout% /R 1 /C random /B M /S ".'.--~'`}"
     %$Cout% /D 1 /X 15 /C random /B M /S "}.-~^'"
     %$Cout% /R 1 /C random /B M /S "'-. '-..'  "
     %$Cout% /D 1 /X 14 /C random /B M /S "{  -'.~('-._,.'"
     %$Cout% /D 1 /X 15 /C random /B M /S "`--; ;  `.  ;"
     %$Cout% /D 1 /X 19 /C random /B M /S "`-..__,-'"
     %$Cout% /T 15 /Y 8 /X 26 /C random /B C /S }
     %$Cout% /D 2 /R 5 /I 2
     %$Cout% /U 1 /R 1 /C 33 /S \
     %$Cout% /Y 25 /X 19 /C random /B M /S ".{EQ}{DQ}-. "
     %$Cout% /D 1 /X 17 /C random /B M /S "_{  '   ; "
     %$Cout% /D 1 /X 15 /C random /B M /S ".~  `."
     %$Cout% /R 1 /C random /B M /S ".'.^`~-. "
     %$Cout% /D 1 /X 14 /C random /B M /S "{   '-."
     %$Cout% /R 1 /C random /B M /S ".'.--~'`}"
     %$Cout% /D 1 /X 15 /C random /B M /S "}.-~^'"
     %$Cout% /R 1 /C random /B M /S "'-. '-..'  "
     %$Cout% /D 1 /X 14 /C random /B M /S "{  -'.~('-._,.'"
     %$Cout% /D 1 /X 15 /C random /B M /S "`--; ;  `.  ;"
     %$Cout% /D 1 /X 19 /C random /B M /S "`-..__,-'"
     %$Cout% /T 15 /Y 8 /X 26 /C random /B B /S {EQ}
     %$Cout% /D 2 /R 5 /Del 2
     %$Cout% /U 1 /R 1 /C 33 /S "|"
     If %%i EQU 25 %$Cout% /H + /Y 34 /X 1 /C 33 /S example 2 done /N
    )
    
    Goto :Eof
    

    【讨论】:

      【解决方案3】:

      Windows 10((版本 1511,内部版本 10586,发布 2015-11-10))支持 ANSI colors
      您可以使用退出键来触发颜色代码。

      在命令提示符中:

      echo ^[[32m HI ^[[0m
      

      回显 Ctrl+[[32m HI Ctrl+[[0mEnter kbd>

      使用文本编辑器时,您可以使用 ALT 键代码。
      可以使用 ALTNUMPAD 数字创建 ESC 键代码:Alt+027

      [32m  HI  [0m
      

      【讨论】:

        【解决方案4】:

        jeb 的编辑答案接近解决所有问题。但它有以下字符串的问题:

        "a\b\"
        "a/b/"
        "\"
        "/"
        "."
        ".."
        "c:"
        

        我已经将他的技术修改为我认为可以真正处理任何可打印字符的字符串,除了长度限制。

        其他改进:

        • 将 %TEMP% 位置用于临时文件,因此不再需要对当前目录的写入权限。

        • 创建了 2 个变体,一个采用字符串文字,另一个采用包含字符串的变量名称。可变版本一般不太方便,但它消除了一些特殊的字符转义问题。

        • 添加 /n 选项作为可选的第三个参数以在输出末尾附加换行符。

        Backspace 在换行时不起作用,因此如果换行,该技术可能会出现问题。例如,如果控制台的线宽为 80,则打印长度在 74 - 79 之间的字符串将无法正常工作。

        @echo off
        setlocal
        
        call :initColorPrint
        
        call :colorPrint 0a "a"
        call :colorPrint 0b "b"
        set "txt=^" & call :colorPrintVar 0c txt
        call :colorPrint 0d "<"
        call :colorPrint 0e ">"
        call :colorPrint 0f "&"
        call :colorPrint 1a "|"
        call :colorPrint 1b " "
        call :colorPrint 1c "%%%%"
        call :colorPrint 1d ^"""
        call :colorPrint 1e "*"
        call :colorPrint 1f "?"
        call :colorPrint 2a "!"
        call :colorPrint 2b "."
        call :colorPrint 2c ".."
        call :colorPrint 2d "/"
        call :colorPrint 2e "\"
        call :colorPrint 2f "q:" /n
        echo(
        set complex="c:\hello world!/.\..\\a//^<%%>&|!" /^^^<%%^>^&^|!\
        call :colorPrintVar 74 complex /n
        
        call :cleanupColorPrint
        
        exit /b
        
        :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
        
        :colorPrint Color  Str  [/n]
        setlocal
        set "str=%~2"
        call :colorPrintVar %1 str %3
        exit /b
        
        :colorPrintVar  Color  StrVar  [/n]
        if not defined %~2 exit /b
        setlocal enableDelayedExpansion
        set "str=a%DEL%!%~2:\=a%DEL%\..\%DEL%%DEL%%DEL%!"
        set "str=!str:/=a%DEL%/..\%DEL%%DEL%%DEL%!"
        set "str=!str:"=\"!"
        pushd "%temp%"
        findstr /p /A:%1 "." "!str!\..\x" nul
        if /i "%~3"=="/n" echo(
        exit /b
        
        :initColorPrint
        for /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do set "DEL=%%a"
        <nul >"%temp%\x" set /p "=%DEL%%DEL%%DEL%%DEL%%DEL%%DEL%.%DEL%"
        exit /b
        
        :cleanupColorPrint
        del "%temp%\x"
        exit /b
        


        2012 年 11 月 27 日更新

        此方法在 XP 上失败,因为 FINDSTR 在屏幕上将退格显示为句点。 jeb 的原始答案适用于 XP,尽管已经指出了限制


        2012 年 12 月 14 日更新

        DosTipsSS64 有很多开发活动。事实证明,如果在命令行上提供 FINDSTR 也会损坏包含扩展 ASCII 的文件名。我已经更新了我的FINDSTR Q&A

        以下是适用于 XP 的版本,支持除 0x00(nul)、0x0A(换行)和 0x0D(回车)之外的所有单字节字符。但是,在 XP 上运行时,大多数控制字符将显示为点。这是 XP 上 FINDSTR 的固有特性,无法避免。

        不幸的是,添加对 XP 和扩展 ASCII 字符的支持会减慢例程速度:-(

        只是为了好玩,我从joan stark's ASCII Art Gallery 获取了一些彩色 ASCII 艺术作品,并将其改编为与 ColorPrint 一起使用。我添加了一个 :c 入口点只是为了速记,并处理引用文字的问题。

        @echo off
        setlocal disableDelayedExpansion
        set q=^"
        echo(
        echo(
        call :c 0E "                ,      .-;" /n
        call :c 0E "             ,  |\    / /  __," /n
        call :c 0E "             |\ '.`-.|  |.'.-'" /n
        call :c 0E "              \`'-:  `; : /" /n
        call :c 0E "               `-._'.  \'|" /n
        call :c 0E "              ,_.-=` ` `  ~,_" /n
        call :c 0E "               '--,.    "&call :c 0c ".-. "&call :c 0E ",=!q!." /n
        call :c 0E "                 /     "&call :c 0c "{ "&call :c 0A "* "&call :c 0c ")"&call :c 0E "`"&call :c 06 ";-."&call :c 0E "}" /n
        call :c 0E "                 |      "&call :c 0c "'-' "&call :c 06 "/__ |" /n
        call :c 0E "                 /          "&call :c 06 "\_,\|" /n
        call :c 0E "                 |          (" /n
        call :c 0E "             "&call :c 0c "__ "&call :c 0E "/ '          \" /n
        call :c 02 "     /\_    "&call :c 0c "/,'`"&call :c 0E "|     '   "&call :c 0c ".-~!q!~~-." /n
        call :c 02 "     |`.\_ "&call :c 0c "|   "&call :c 0E "/  ' ,    "&call :c 0c "/        \" /n
        call :c 02 "   _/  `, \"&call :c 0c "|  "&call :c 0E "; ,     . "&call :c 0c "|  ,  '  . |" /n
        call :c 02 "   \   `,  "&call :c 0c "|  "&call :c 0E "|  ,  ,   "&call :c 0c "|  :  ;  : |" /n
        call :c 02 "   _\  `,  "&call :c 0c "\  "&call :c 0E "|.     ,  "&call :c 0c "|  |  |  | |" /n
        call :c 02 "   \`  `.   "&call :c 0c "\ "&call :c 0E "|   '     "&call :c 0A "|"&call :c 0c "\_|-'|_,'\|" /n
        call :c 02 "   _\   `,   "&call :c 0A "`"&call :c 0E "\  '  . ' "&call :c 0A "| |  | |  |           "&call :c 02 "__" /n
        call :c 02 "   \     `,   "&call :c 0E "| ,  '    "&call :c 0A "|_/'-|_\_/     "&call :c 02 "__ ,-;` /" /n
        call :c 02 "    \    `,    "&call :c 0E "\ .  , ' .| | | | |   "&call :c 02 "_/' ` _=`|" /n
        call :c 02 "     `\    `,   "&call :c 0E "\     ,  | | | | |"&call :c 02 "_/'   .=!q!  /" /n
        call :c 02 "     \`     `,   "&call :c 0E "`\      \/|,| ;"&call :c 02 "/'   .=!q!    |" /n
        call :c 02 "      \      `,    "&call :c 0E "`\' ,  | ; "&call :c 02 "/'    =!q!    _/" /n
        call :c 02 "       `\     `,  "&call :c 05 ".-!q!!q!-. "&call :c 0E "': "&call :c 02 "/'    =!q!     /" /n
        call :c 02 "    jgs _`\    ;"&call :c 05 "_{  '   ; "&call :c 02 "/'    =!q!      /" /n
        call :c 02 "       _\`-/__"&call :c 05 ".~  `."&call :c 07 "8"&call :c 05 ".'.!q!`~-. "&call :c 02 "=!q!     _,/" /n
        call :c 02 "    __\      "&call :c 05 "{   '-."&call :c 07 "|"&call :c 05 ".'.--~'`}"&call :c 02 "    _/" /n
        call :c 02 "    \    .=!q!` "&call :c 05 "}.-~!q!'"&call :c 0D "u"&call :c 05 "'-. '-..'  "&call :c 02 "__/" /n
        call :c 02 "   _/  .!q!    "&call :c 05 "{  -'.~('-._,.'"&call :c 02 "\_,/" /n
        call :c 02 "  /  .!q!    _/'"&call :c 05 "`--; ;  `.  ;" /n
        call :c 02 "   .=!q!  _/'      "&call :c 05 "`-..__,-'" /n
        call :c 02 "    __/'" /n
        echo(
        
        exit /b
        
        :c
        setlocal enableDelayedExpansion
        :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
        
        :colorPrint Color  Str  [/n]
        setlocal
        set "s=%~2"
        call :colorPrintVar %1 s %3
        exit /b
        
        :colorPrintVar  Color  StrVar  [/n]
        if not defined DEL call :initColorPrint
        setlocal enableDelayedExpansion
        pushd .
        ':
        cd \
        set "s=!%~2!"
        :: The single blank line within the following IN() clause is critical - DO NOT REMOVE
        for %%n in (^"^
        
        ^") do (
          set "s=!s:\=%%~n\%%~n!"
          set "s=!s:/=%%~n/%%~n!"
          set "s=!s::=%%~n:%%~n!"
        )
        for /f delims^=^ eol^= %%s in ("!s!") do (
          if "!" equ "" setlocal disableDelayedExpansion
          if %%s==\ (
            findstr /a:%~1 "." "\'" nul
            <nul set /p "=%DEL%%DEL%%DEL%"
          ) else if %%s==/ (
            findstr /a:%~1 "." "/.\'" nul
            <nul set /p "=%DEL%%DEL%%DEL%%DEL%%DEL%"
          ) else (
            >colorPrint.txt (echo %%s\..\')
            findstr /a:%~1 /f:colorPrint.txt "."
            <nul set /p "=%DEL%%DEL%%DEL%%DEL%%DEL%%DEL%%DEL%"
          )
        )
        if /i "%~3"=="/n" echo(
        popd
        exit /b
        
        
        :initColorPrint
        for /f %%A in ('"prompt $H&for %%B in (1) do rem"') do set "DEL=%%A %%A"
        <nul >"%temp%\'" set /p "=."
        subst ': "%temp%" >nul
        exit /b
        
        
        :cleanupColorPrint
        2>nul del "%temp%\'"
        2>nul del "%temp%\colorPrint.txt"
        >nul subst ': /d
        exit /b
        

        【讨论】:

        • 有没有办法让这个脚本处理那些用来制作类似dos的菜单的字符? en.wikipedia.org/wiki/Box-drawing_character
        • @Elieder - 你试过了吗?它应该可以工作,但是您需要在变量中获取适当的扩展 ASCII 代码,并且必须正确设置您的活动代码页。如果您不能让它发挥作用,请提出一个新问题。
        • 我遇到了一个问题,我希望显示 '## %76 space% ##',但它显示为 '## \.##' 我不知道为什么,下面是我的代码:'call :c 0e "##"&call :c f9 "%76 Spaces%"&call :c 0a "##"'
        • 似乎出现的外来字符是\..\':。它们出现在每一行(因为我的内容是 80 chr,而我的窗框是 80chr
        • @level42 - 窗口宽度必须比最长行宽一点,因为它会写入不需要的字符,然后使用退格键将其擦除。如果它超过了屏幕宽度,那么退格就不能再擦除它们了。
        【解决方案5】:

        Without external tools.这是一个自编译的bat/.net hybrid(应保存为.BAT),可以在任何安装了.net framework的系统上使用(它是一个即使对于最古老的 XP/2003 安装,也很少看到没有 .NET 框架的 Windows)。它使用 jscript.net 编译器创建一个 exe,能够为当前行打印具有不同背景/前景色的字符串。

        @if (@X)==(@Y) @end /* JScript comment
        @echo off
        setlocal
        
        for /f "tokens=* delims=" %%v in ('dir /b /s /a:-d  /o:-n "%SystemRoot%\Microsoft.NET\Framework\*jsc.exe"') do (
           set "jsc=%%v"
        )
        
        if not exist "%~n0.exe" (
            "%jsc%" /nologo /out:"%~n0.exe" "%~dpsfnx0"
        )
        
        %~n0.exe %*
        
        endlocal & exit /b %errorlevel%
        
        */
        
        import System;
        
        var arguments:String[] = Environment.GetCommandLineArgs();
        
        var newLine = false;
        var output = "";
        var foregroundColor = Console.ForegroundColor;
        var backgroundColor = Console.BackgroundColor;
        var evaluate = false;
        var currentBackground=Console.BackgroundColor;
        var currentForeground=Console.ForegroundColor;
        
        
        //http://stackoverflow.com/a/24294348/388389
        var jsEscapes = {
          'n': '\n',
          'r': '\r',
          't': '\t',
          'f': '\f',
          'v': '\v',
          'b': '\b'
        };
        
        function decodeJsEscape(_, hex0, hex1, octal, other) {
          var hex = hex0 || hex1;
          if (hex) { return String.fromCharCode(parseInt(hex, 16)); }
          if (octal) { return String.fromCharCode(parseInt(octal, 8)); }
          return jsEscapes[other] || other;
        }
        
        function decodeJsString(s) {
          return s.replace(
              // Matches an escape sequence with UTF-16 in group 1, single byte hex in group 2,
              // octal in group 3, and arbitrary other single-character escapes in group 4.
              /\\(?:u([0-9A-Fa-f]{4})|x([0-9A-Fa-f]{2})|([0-3][0-7]{0,2}|[4-7][0-7]?)|(.))/g,
              decodeJsEscape);
        }
        
        
        function printHelp( ) {
           print( arguments[0] + "  -s string [-f foreground] [-b background] [-n] [-e]" );
           print( " " );
           print( " string          String to be printed" );
           print( " foreground      Foreground color - a " );
           print( "                 number between 0 and 15." );
           print( " background      Background color - a " );
           print( "                 number between 0 and 15." );
           print( " -n              Indicates if a new line should" );
           print( "                 be written at the end of the ");
           print( "                 string(by default - no)." );
           print( " -e              Evaluates special character " );
           print( "                 sequences like \\n\\b\\r and etc ");
           print( "" );
           print( "Colors :" );
           for ( var c = 0 ; c < 16 ; c++ ) {
        
                Console.BackgroundColor = c;
                Console.Write( " " );
                Console.BackgroundColor=currentBackground;
                Console.Write( "-"+c );
                Console.WriteLine( "" );
           }
           Console.BackgroundColor=currentBackground;
        
        
        
        }
        
        function errorChecker( e:Error ) {
                if ( e.message == "Input string was not in a correct format." ) {
                    print( "the color parameters should be numbers between 0 and 15" );
                    Environment.Exit( 1 );
                } else if (e.message == "Index was outside the bounds of the array.") {
                    print( "invalid arguments" );
                    Environment.Exit( 2 );
                } else {
                    print ( "Error Message: " + e.message );
                    print ( "Error Code: " + ( e.number & 0xFFFF ) );
                    print ( "Error Name: " + e.name );
                    Environment.Exit( 666 );
                }
        }
        
        function numberChecker( i:Int32 ){
            if( i > 15 || i < 0 ) {
                print("the color parameters should be numbers between 0 and 15");
                Environment.Exit(1);
            }
        }
        
        
        if ( arguments.length == 1 || arguments[1].toLowerCase() == "-help" || arguments[1].toLowerCase() == "-help"   ) {
            printHelp();
            Environment.Exit(0);
        }
        
        for (var arg = 1; arg <= arguments.length-1; arg++ ) {
            if ( arguments[arg].toLowerCase() == "-n" ) {
                newLine=true;
            }
        
            if ( arguments[arg].toLowerCase() == "-e" ) {
                evaluate=true;
            }
        
            if ( arguments[arg].toLowerCase() == "-s" ) {
                output=arguments[arg+1];
            }
        
        
            if ( arguments[arg].toLowerCase() == "-b" ) {
        
                try {
                    backgroundColor=Int32.Parse( arguments[arg+1] );
                } catch(e) {
                    errorChecker(e);
                }
            }
        
            if ( arguments[arg].toLowerCase() == "-f" ) {
                try {
                    foregroundColor=Int32.Parse(arguments[arg+1]);
                } catch(e) {
                    errorChecker(e);
                }
            }
        }
        
        Console.BackgroundColor = backgroundColor ;
        Console.ForegroundColor = foregroundColor ;
        
        if ( evaluate ) {
            output=decodeJsString(output);
        }
        
        if ( newLine ) {
            Console.WriteLine(output);  
        } else {
            Console.Write(output);
        
        }
        
        Console.BackgroundColor = currentBackground;
        Console.ForegroundColor = currentForeground;
        

        例如coloroutput.bat -s "aa\nbb\n\u0025cc" -b 10 -f 3 -n -e

        你也可以查看卡洛斯的颜色功能 -> http://www.dostips.com/forum/viewtopic.php?f=3&t=4453

        【讨论】:

          【解决方案6】:

          如果您的控制台支持 ANSI 颜色代码(例如 ConEmuClinkANSICON),您可以这样做:

          SET    GRAY=%ESC%[0m
          SET     RED=%ESC%[1;31m
          SET   GREEN=%ESC%[1;32m
          SET  ORANGE=%ESC%[0;33m
          SET    BLUE=%ESC%[0;34m
          SET MAGENTA=%ESC%[0;35m
          SET    CYAN=%ESC%[1;36m
          SET   WHITE=%ESC%[1;37m
          

          其中 ESC 变量包含 ASCII 字符 27。

          我在这里找到了一种填充 ESC 变量的方法:http://www.dostips.com/forum/viewtopic.php?p=6827#p6827 并使用tasklist 可以测试将哪些DLL 加载到进程中。

          以下脚本获取运行该脚本的 cmd.exe 的进程 ID。检查它是否具有将添加 ANSI 支持注入的 dll,然后根据是否设置颜色变量以包含转义序列或为空是否支持颜色。

          @echo off
          
          call :INIT_COLORS
          
          echo %RED%RED %GREEN%GREEN %ORANGE%ORANGE %BLUE%BLUE %MAGENTA%MAGENTA %CYAN%CYAN %WHITE%WHITE %GRAY%GRAY
          
          :: pause if double clicked on instead of run from command line.
          SET interactive=0
          ECHO %CMDCMDLINE% | FINDSTR /L %COMSPEC% >NUL 2>&1
          IF %ERRORLEVEL% == 0 SET interactive=1
          @rem ECHO %CMDCMDLINE% %COMSPEC% %interactive%
          IF "%interactive%"=="1" PAUSE
          EXIT /B 0
          Goto :EOF
          
          ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
          : SUBROUTINES                                                          :
          ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
          
          ::::::::::::::::::::::::::::::::
          :INIT_COLORS
          ::::::::::::::::::::::::::::::::
          
          call :supportsANSI
          if ERRORLEVEL 1 (
            SET GREEN=
            SET RED=
            SET GRAY=
            SET WHITE=
            SET ORANGE=
            SET CYAN=
          ) ELSE (
          
            :: If you can, insert ASCII CHAR 27 after equals and remove BL.String.CreateDEL_ESC routine
            set "ESC="
            :: use this if can't type ESC CHAR, it's more verbose, but you can copy and paste it
            call :BL.String.CreateDEL_ESC
          
            SET    GRAY=%ESC%[0m
            SET     RED=%ESC%[1;31m
            SET   GREEN=%ESC%[1;32m
            SET  ORANGE=%ESC%[0;33m
            SET    BLUE=%ESC%[0;34m
            SET MAGENTA=%ESC%[0;35m
            SET    CYAN=%ESC%[1;36m
            SET   WHITE=%ESC%[1;37m
          )
          
          exit /b
          
          ::::::::::::::::::::::::::::::::
          :BL.String.CreateDEL_ESC
          ::::::::::::::::::::::::::::::::
          :: http://www.dostips.com/forum/viewtopic.php?t=1733
          ::
          :: Creates two variables with one character DEL=Ascii-08 and ESC=Ascii-27
          :: DEL and ESC can be used  with and without DelayedExpansion
          setlocal
          for /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (
            ENDLOCAL
            set "DEL=%%a"
            set "ESC=%%b"
            goto :EOF
          )
          
          ::::::::::::::::::::::::::::::::
          :supportsANSI
          ::::::::::::::::::::::::::::::::
          :: returns ERRORLEVEL 0 - YES, 1 - NO
          ::
          :: - Tests for ConEmu, ANSICON and Clink
          :: - Returns 1 - NO support, when called via "CMD /D" (i.e. no autoruns / DLL injection)
          ::   on a system that would otherwise support ANSI.
          
          if "%ConEmuANSI%" == "ON" exit /b 0
          
          call :getPID PID
          
          setlocal
          
          for /f usebackq^ delims^=^"^ tokens^=^* %%a in (`tasklist /fi "PID eq %PID%" /m /fo CSV`) do set "MODULES=%%a"
          
          set MODULES=%MODULES:"=%
          set NON_ANSI_MODULES=%MODULES%
          
          :: strip out ANSI dlls from module list:
          :: ANSICON adds ANSI64.dll or ANSI32.dll
          set "NON_ANSI_MODULES=%NON_ANSI_MODULES:ANSI=%"
          :: ConEmu attaches ConEmuHk but ConEmu also sets ConEmuANSI Environment VAR
          :: so we've already checked for that above and returned early.
          @rem set "NON_ANSI_MODULES=%NON_ANSI_MODULES:ConEmuHk=%"
          :: Clink supports ANSI https://github.com/mridgers/clink/issues/54
          set "NON_ANSI_MODULES=%NON_ANSI_MODULES:clink_dll=%"
          
          if "%MODULES%" == "%NON_ANSI_MODULES%" endlocal & exit /b 1
          endlocal
          
          exit /b 0
          
          ::::::::::::::::::::::::::::::::
          :getPID  [RtnVar]
          ::::::::::::::::::::::::::::::::
          :: REQUIREMENTS:
          ::
          :: Determine the Process ID of the currently executing script,
          :: but in a way that is multiple execution safe especially when the script can be executing multiple times
          ::   - at the exact same time in the same millisecond,
          ::   - by multiple users,
          ::   - in multiple window sessions (RDP),
          ::   - by privileged and non-privileged (e.g. Administrator) accounts,
          ::   - interactively or in the background.
          ::   - work when the cmd.exe window cannot appear
          ::     e.g. running from TaskScheduler as LOCAL SERVICE or using the "Run whether user is logged on or not" setting
          ::
          :: https://social.msdn.microsoft.com/Forums/vstudio/en-US/270f0842-963d-4ed9-b27d-27957628004c/what-is-the-pid-of-the-current-cmdexe?forum=msbuild
          ::
          :: http://serverfault.com/a/654029/306
          ::
          :: Store the Process ID (PID) of the currently running script in environment variable RtnVar.
          :: If called without any argument, then simply write the PID to stdout.
          ::
          ::
          setlocal disableDelayedExpansion
          :getLock
          set "lock=%temp%\%~nx0.%time::=.%.lock"
          set "uid=%lock:\=:b%"
          set "uid=%uid:,=:c%"
          set "uid=%uid:'=:q%"
          set "uid=%uid:_=:u%"
          setlocal enableDelayedExpansion
          set "uid=!uid:%%=:p!"
          endlocal & set "uid=%uid%"
          2>nul ( 9>"%lock%" (
            for /f "skip=1" %%A in (
              'wmic process where "name='cmd.exe' and CommandLine like '%%<%uid%>%%'" get ParentProcessID'
            ) do for %%B in (%%A) do set "PID=%%B"
            (call )
          ))||goto :getLock
          del "%lock%" 2>nul
          endlocal & if "%~1" equ "" (echo(%PID%) else set "%~1=%PID%"
          exit /b
          

          【讨论】:

            【解决方案7】:

            结合dbenham's bird and syntaxskrebbel's powershell write-host method,看来powershell 可以比dbenham 的纯批处理方法更快地渲染复杂的艺术作品(好吧,无论如何,在powershell 启动一次之后)。需要对琴弦进行最少的按摩,尽管我没有用鸟以外的任何东西对此进行过测试。例如,如果您想要一个亮绿色的​​传输结束字符,那么您可能不走运。 :)

            这种方法需要回显到一个临时文件,因为为每个call :c 调用 powershell 需要很长时间,而且为一个 powershell 调用排队输出要快得多。但它确实具有简单和高效的优点。

            @echo off
            setlocal disableDelayedExpansion
            set q=^"
            echo(
            echo(
            call :c 0E "                ,      .-;" /n
            call :c 0E "             ,  |\    / /  __," /n
            call :c 0E "             |\ '.`-.|  |.'.-'" /n
            call :c 0E "              \`'-:  `; : /" /n
            call :c 0E "               `-._'.  \'|" /n
            call :c 0E "              ,_.-=` ` `  ~,_" /n
            call :c 0E "               '--,.    "&call :c 0c ".-. "&call :c 0E ",=!q!." /n
            call :c 0E "                 /     "&call :c 0c "{ "&call :c 0A "* "&call :c 0c ")"&call :c 0E "`"&call :c 06 ";-."&call :c 0E "}" /n
            call :c 0E "                 |      "&call :c 0c "'-' "&call :c 06 "/__ |" /n
            call :c 0E "                 /          "&call :c 06 "\_,\|" /n
            call :c 0E "                 |          (" /n
            call :c 0E "             "&call :c 0c "__ "&call :c 0E "/ '          \" /n
            call :c 02 "     /\_    "&call :c 0c "/,'`"&call :c 0E "|     '   "&call :c 0c ".-~!q!~~-." /n
            call :c 02 "     |`.\_ "&call :c 0c "|   "&call :c 0E "/  ' ,    "&call :c 0c "/        \" /n
            call :c 02 "   _/  `, \"&call :c 0c "|  "&call :c 0E "; ,     . "&call :c 0c "|  ,  '  . |" /n
            call :c 02 "   \   `,  "&call :c 0c "|  "&call :c 0E "|  ,  ,   "&call :c 0c "|  :  ;  : |" /n
            call :c 02 "   _\  `,  "&call :c 0c "\  "&call :c 0E "|.     ,  "&call :c 0c "|  |  |  | |" /n
            call :c 02 "   \`  `.   "&call :c 0c "\ "&call :c 0E "|   '     "&call :c 0A "|"&call :c 0c "\_|-'|_,'\|" /n
            call :c 02 "   _\   `,   "&call :c 0A "`"&call :c 0E "\  '  . ' "&call :c 0A "| |  | |  |           "&call :c 02 "__" /n
            call :c 02 "   \     `,   "&call :c 0E "| ,  '    "&call :c 0A "|_/'-|_\_/     "&call :c 02 "__ ,-;` /" /n
            call :c 02 "    \    `,    "&call :c 0E "\ .  , ' .| | | | |   "&call :c 02 "_/' ` _=`|" /n
            call :c 02 "     `\    `,   "&call :c 0E "\     ,  | | | | |"&call :c 02 "_/'   .=!q!  /" /n
            call :c 02 "     \`     `,   "&call :c 0E "`\      \/|,| ;"&call :c 02 "/'   .=!q!    |" /n
            call :c 02 "      \      `,    "&call :c 0E "`\' ,  | ; "&call :c 02 "/'    =!q!    _/" /n
            call :c 02 "       `\     `,  "&call :c 05 ".-!q!!q!-. "&call :c 0E "': "&call :c 02 "/'    =!q!     /" /n
            call :c 02 "    jgs _`\    ;"&call :c 05 "_{  '   ; "&call :c 02 "/'    =!q!      /" /n
            call :c 02 "       _\`-/__"&call :c 05 ".~  `."&call :c 07 "8"&call :c 05 ".'.!q!`~-. "&call :c 02 "=!q!     _,/" /n
            call :c 02 "    __\      "&call :c 05 "{   '-."&call :c 07 "|"&call :c 05 ".'.--~'`}"&call :c 02 "    _/" /n
            call :c 02 "    \    .=!q!` "&call :c 05 "}.-~!q!'"&call :c 0D "u"&call :c 05 "'-. '-..'  "&call :c 02 "__/" /n
            call :c 02 "   _/  .!q!    "&call :c 05 "{  -'.~('-._,.'"&call :c 02 "\_,/" /n
            call :c 02 "  /  .!q!    _/'"&call :c 05 "`--; ;  `.  ;" /n
            call :c 02 "   .=!q!  _/'      "&call :c 05 "`-..__,-'" /n
            call :c 02 "    __/'" /n
            
            if exist "%temp%\color.psm1" (
                powershell -command "&{set-executionpolicy remotesigned; Import-Module '%temp%\color.psm1'}"
                del "%temp%\color.psm1"
            )
            
            echo(
            
            exit /b
            
            :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
            
            :c <color pair> <string> </n>
            setlocal enabledelayedexpansion
            set "colors=0-black;1-darkblue;2-darkgreen;3-darkcyan;4-darkred;5-darkmagenta;6-darkyellow;7-gray;8-darkgray;9-blue;a-green;b-cyan;c-red;d-magenta;e-yellow;f-white"
            set "p=%~1"
            set "bg=!colors:*%p:~0,1%-=!"
            set bg=%bg:;=&rem.%
            set "fg=!colors:*%p:~-1%-=!"
            set fg=%fg:;=&rem.%
            
            if not "%~3"=="/n" set "br=-nonewline"
            set "str=%~2" & set "str=!str:'=''!"
            
            >>"%temp%\color.psm1" echo write-host '!str!' -foregroundcolor '%fg%' -backgroundcolor '%bg%' %br%
            endlocal
            

            结果:

            【讨论】:

              【解决方案8】:

              是的,cmdcolor

              echo \033[32mhi \033[92mworld
              

              hi 将是深绿色,world - 浅绿色。

              【讨论】:

              • 与纯批处理解决方案相比,这个速度相当快。谢谢。
              【解决方案9】:

              如果您有现代 Windows(安装了 powershell),以下可能也可以正常工作

              call :PrintBright Something Something
              
                (do actual batch stuff here)
              
              call :PrintBright Done!
              goto :eof
              
              
              :PrintBright
              powershell -Command Write-Host "%*" -foreground "White"
              

              根据您的需要调整颜色。

              【讨论】:

              【解决方案10】:

              实际上这可以在不创建临时文件的情况下完成。 jeb 和 dbenham 描述的方法甚至适用于不包含退格的目标文件。关键点是 findstr.exe 识别的行不能以 CRLF 结尾。 因此,不以 CRLF 结尾的行扫描的明显文本文件就是调用批处理本身,前提是我们以这样的行结尾! 这是一个以这种方式工作的更新示例脚本...

              与上一个示例的变化:

              • 在最后一行使用一个短划线作为可搜索字符串。 (必须很短,并且不能出现在批次中的其他任何地方。)
              • 将例程和变量重命名为更加面向对象:-)
              • 删除了一个调用级别,以略微提高性能。
              • 添加了 cmets(以 :# 开头,看起来更像大多数其他脚本语言。)

              @echo off
              setlocal
              
              call :Echo.Color.Init
              
              goto main
              
              :Echo.Color %1=Color %2=Str [%3=/n]
              setlocal enableDelayedExpansion
              set "str=%~2"
              :Echo.Color.2
              :# Replace path separators in the string, so that the final path still refers to the current path.
              set "str=a%ECHO.DEL%!str:\=a%ECHO.DEL%\..\%ECHO.DEL%%ECHO.DEL%%ECHO.DEL%!"
              set "str=!str:/=a%ECHO.DEL%/..\%ECHO.DEL%%ECHO.DEL%%ECHO.DEL%!"
              set "str=!str:"=\"!"
              :# Go to the script directory and search for the trailing -
              pushd "%ECHO.DIR%"
              findstr /p /r /a:%~1 "^^-" "!str!\..\!ECHO.FILE!" nul
              popd
              :# Remove the name of this script from the output. (Dependant on its length.)
              for /l %%n in (1,1,12) do if not "!ECHO.FILE:~%%n!"=="" <nul set /p "=%ECHO.DEL%"
              :# Remove the other unwanted characters "\..\: -"
              <nul set /p "=%ECHO.DEL%%ECHO.DEL%%ECHO.DEL%%ECHO.DEL%%ECHO.DEL%%ECHO.DEL%%ECHO.DEL%"
              :# Append the optional CRLF
              if not "%~3"=="" echo.
              endlocal & goto :eof
              
              :Echo.Color.Var %1=Color %2=StrVar [%3=/n]
              if not defined %~2 goto :eof
              setlocal enableDelayedExpansion
              set "str=!%~2!"
              goto :Echo.Color.2
              
              :Echo.Color.Init
              set "ECHO.COLOR=call :Echo.Color"
              set "ECHO.DIR=%~dp0"
              set "ECHO.FILE=%~nx0"
              set "ECHO.FULL=%ECHO.DIR%%ECHO.FILE%"
              :# Use prompt to store a backspace into a variable. (Actually backspace+space+backspace)
              for /F "tokens=1 delims=#" %%a in ('"prompt #$H# & echo on & for %%b in (1) do rem"') do set "ECHO.DEL=%%a"
              goto :eof
              
              :main
              call :Echo.Color 0a "a"
              call :Echo.Color 0b "b"
              set "txt=^" & call :Echo.Color.Var 0c txt
              call :Echo.Color 0d "<"
              call :Echo.Color 0e ">"
              call :Echo.Color 0f "&"
              call :Echo.Color 1a "|"
              call :Echo.Color 1b " "
              call :Echo.Color 1c "%%%%"
              call :Echo.Color 1d ^"""
              call :Echo.Color 1e "*"
              call :Echo.Color 1f "?"
              :# call :Echo.Color 2a "!"
              call :Echo.Color 2b "."
              call :Echo.Color 2c ".."
              call :Echo.Color 2d "/"
              call :Echo.Color 2e "\"
              call :Echo.Color 2f "q:" /n
              echo(
              set complex="c:\hello world!/.\..\\a//^<%%>&|!" /^^^<%%^>^&^|!\
              call :Echo.Color.Var 74 complex /n
              
              exit /b
              
              :# The following line must be last and not end by a CRLF.
              -
              

              PS。我的输出有问题!上一个示例中没有的字符。 (或者至少你没有相同的症状。)待调查。

              【讨论】:

              • ! 的问题可以通过call :Echo.Color 2f ^^^! 或在调用使用call :Echo.Color 2f ^^^^^^^! 时启用延迟扩展来解决
              • 嗨,也许我遗漏了一些东西,但我在 Win 8.1 Update 1 上的命令提示符(非管理员)中逐行使用你上面的示例,我得到以下信息输出:i.imgur.com/1CsOWdu.png - 对吗?谢谢
              • 有趣的想法,但我不会使用这种技术,因为脚本名称应该是描述性的,但是名称越长,每行末尾的死区就越多,无法进行彩色打印.我总是使用长度为 1 的文件名,但这不能描述,所以我使用临时文件。
              • 无需担心唯一的行。您可以通过使用带有$ 搜索字符串的/V 选项来简单地查找不包含CR 的行。 FINDSTR 正则表达式 $ 锚寻找 CR!此外,不需要每次都计算文件名的长度。这可以在初始化期间完成,删除字符可以合并到字符串“常量”中。
              【解决方案11】:


              中介绍了几种方法 "51} 如何在 NT 脚本中以不同颜色回显线条?"
              http://www.netikka.net/tsneti/info/tscmd051.htm

              其中一种选择:如果你能掌握 QBASIC,使用颜色相对容易:

                @echo off & setlocal enableextensions
                for /f "tokens=*" %%f in ("%temp%") do set temp_=%%~sf
                set skip=
                findstr "'%skip%QB" "%~f0" > %temp_%\tmp$$$.bas
                qbasic /run %temp_%\tmp$$$.bas
                for %%f in (%temp_%\tmp$$$.bas) do if exist %%f del %%f
                endlocal & goto :EOF
                ::
                CLS 'QB
                COLOR 14,0 'QB
                PRINT "A simple "; 'QB
                COLOR 13,0 'QB
                PRINT "color "; 'QB
                COLOR 14,0 'QB
                PRINT "demonstration" 'QB
                PRINT "By Prof. (emer.) Timo Salmi" 'QB
                PRINT 'QB
                FOR j = 0 TO 7 'QB
                  FOR i = 0 TO 15 'QB
                    COLOR i, j 'QB
                    PRINT LTRIM$(STR$(i)); " "; LTRIM$(STR$(j)); 'QB
                    COLOR 1, 0 'QB
                    PRINT " "; 'QB
                  NEXT i 'QB
                  PRINT 'QB
                NEXT j 'QB
                SYSTEM 'QB
              

              【讨论】:

              【解决方案12】:

              您可以在没有任何外部程序的情况下进行多色输出。

              @echo off
              SETLOCAL EnableDelayedExpansion
              for /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (
                set "DEL=%%a"
              )
              echo say the name of the colors, don't read
              
              call :ColorText 0a "blue"
              call :ColorText 0C "green"
              call :ColorText 0b "red"
              echo(
              call :ColorText 19 "yellow"
              call :ColorText 2F "black"
              call :ColorText 4e "white"
              
              goto :eof
              
              :ColorText
              echo off
              <nul set /p ".=%DEL%" > "%~2"
              findstr /v /a:%1 /R "^$" "%~2" nul
              del "%~2" > nul 2>&1
              goto :eof
              

              它使用 findstr 命令的颜色特性。

              Findstr 可以配置为以定义的颜色输出行号或文件名。
              所以我首先创建了一个文件,文件名是文本,内容是单个&lt;backspace&gt; 字符(ASCII 8)。
              然后我在文件和 nul 中搜索所有非空行,因此文件名将以正确的颜色输出并附加一个冒号,但冒号会立即被 &lt;backspace&gt; 删除。

              编辑:一年后...所有字符都有效

              @echo off
              setlocal EnableDelayedExpansion
              for /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (
                set "DEL=%%a"
              )
              
              rem Prepare a file "X" with only one dot
              <nul > X set /p ".=."
              
              call :color 1a "a"
              call :color 1b "b"
              call :color 1c "^!<>&| %%%%"*?"
              exit /b
              
              :color
              set "param=^%~2" !
              set "param=!param:"=\"!"
              findstr /p /A:%1 "." "!param!\..\X" nul
              <nul set /p ".=%DEL%%DEL%%DEL%%DEL%%DEL%%DEL%%DEL%"
              exit /b
              

              这使用有效路径/文件名的规则。
              如果\..\ 在路径中,则前缀元素将被完全删除,并且此元素不必仅包含有效的文件名字符。

              【讨论】:

              • 好的,这很好,但是有什么方法可以减少输入一行代码的数量来做到这一点?我是否可以将其设置为名为“defcolor”的全局变量,并且每次打开命令提示符时都可以使用它? (通过导入或将其作为系统变量?)
              • 你能给我看一个我可以用来做这个的模板吗?就像“findstr”命令的模板一样,类似于“FINDSTR /A /File[Filename] /Path[path]”,我可以将其用作未来使用的指南。
              • @Mr. Bungle:但是现在,所有其他角色也都可以使用 :-)
              • 要移动到换行符,只需使用echo(
              • 你应该在退出之前删除你的临时文件.. del /f /q X ;) 非常好的解决方案..
              【解决方案13】:

              你应该下载 chgcolor.zip 从 http://www.mailsend-online.com/blog/setting-text-color-in-a-batch-file.html 并从下载 echoj.zip www.mailsend-online.com/blog/?p=41 它们都位于页面底部。 将两个文件夹解压到桌面 并将提取的文件夹中的可执行文件(.exe 文件)复制到 C:\Windows 目录。这将允许它们从命令行执行。 打开记事本,复制以下内容:

              @echo 关闭

              chgcolor 03

              回声“嗨”

              chgcolor 0d

              echoj "世界"

              chgcolor 07

              echoj $0a

              将文件作为 hi.bat 保存到桌面。现在打开命令提示符并导航到您的桌面文件夹并键入不带引号的“hi.bat”。这应该让您开始一定要阅读这两个网页以获取完整的教程。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2017-07-25
                • 1970-01-01
                • 2016-02-07
                • 2023-02-10
                • 1970-01-01
                • 2010-11-24
                相关资源
                最近更新 更多