How to have multiple colors in a Windows batch file?

前端 未结 12 1613
我寻月下人不归
我寻月下人不归 2020-11-22 01:05

I was wondering if its possible to have different colored text on the same line in a Windows batch file, for example if it says

echo hi world
12条回答
  •  庸人自扰
    2020-11-22 01:36

    jeb's edited answer comes close to solving all the issues. But it has problems with the following strings:

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

    I've modified his technique to something that I think can truly handle any string of printable characters, except for length limitations.

    Other improvements:

    • Uses the %TEMP% location for the temp file, so no longer need write access to the current directory.

    • Created 2 variants, one takes a string literal, the other the name of a variable containing the string. The variable version is generally less convenient, but it eliminates some special character escape issues.

    • Added the /n option as an optional 3rd parameter to append a newline at the end of the output.

    Backspace does not work across a line break, so the technique can have problems if the line wraps. For example, printing a string with length between 74 - 79 will not work properly if the console has a line width of 80.

    @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"
    "%temp%\x" set /p "=%DEL%%DEL%%DEL%%DEL%%DEL%%DEL%.%DEL%"
    exit /b
    
    :cleanupColorPrint
    del "%temp%\x"
    exit /b
    


    UPDATE 2012-11-27

    This method fails on XP because FINDSTR displays backspace as a period on the screen. jeb's original answer works on XP, albeit with the limitations already noted


    UPDATE 2012-12-14

    There has been a lot of development activity at DosTips and SS64. It turns out that FINDSTR also corrupts file names containing extended ASCII if supplied on the command line. I've updated my FINDSTR Q&A.

    Below is a version that works on XP and supports ALL single byte characters except 0x00 (nul), 0x0A (linefeed), and 0x0D (carriage return). However, when running on XP, most control characters will display as dots. This is an inherent feature of FINDSTR on XP that cannot be avoided.

    Unfortunately, adding support for XP and for extended ASCII characters slows the routine down :-(

    Just for fun, I grabbed some color ASCII art from joan stark's ASCII Art Gallery and adapted it for use with ColorPrint. I added a :c entry point just for shorthand, and to handle an issue with quote literals.

    @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
        colorPrint.txt (echo %%s\..\')
        findstr /a:%~1 /f:colorPrint.txt "."
        "%temp%\'" set /p "=."
    subst ': "%temp%" >nul
    exit /b
    
    
    :cleanupColorPrint
    2>nul del "%temp%\'"
    2>nul del "%temp%\colorPrint.txt"
    >nul subst ': /d
    exit /b
    

提交回复
热议问题