Windows批处理文件中如何具有多种颜色?


74

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

echo hi world

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

set color1= color 2
set color9= color A

然后将它们与

echo hi world

但我不知道该怎么做。

Answers:


27

实际上,无需创建临时文件即可完成此操作。jeb和dbenham描述的方法即使对于不包含退格键的目标文件也可以使用。关键点是findstr.exe识别的行不得以CRLF结尾。因此,要以不以CRLF结尾的行进行扫描的显而易见的文本文件就是调用批处理本身,只要我们以这样的行结尾即可!这是以此方式工作的更新示例脚本...

与上一个示例相比的变化:

  • 在最后一行使用一个破折号作为可搜索字符串。(必须简短,并且不得在批处理中出现在其他任何地方。)
  • 重命名例程和变量,使其更加面向对象:-)
  • 删除了一个呼叫级别,以略微提高性能。
  • 添加了注释(从:#开始看起来更像大多数其他脚本语言。)

@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。我的输出有问题!您在上一个示例中没有的字符。(或者至少您没有相同的症状。)进行调查。


5
!可以使用call :Echo.Color 2f ^^^!或在调用use时启用延迟扩展来解决的问题call :Echo.Color 2f ^^^^^^^!
jeb 2012年

嗨,也许我遗漏了一些东西,但我使用的是上面的示例,在Win 8.1 Update 1的命令提示符(非管理员)中逐行显示,并且得到以下输出:i.imgur.com/ 1CsOWdu.png-是吗?感谢
Adam Plocher 2014年

有趣的主意,但我不会使用此技术,因为脚本名称应具有描述性,但名称越长,每行末尾无法打印彩色的死空间就越大。我将始终使用文件名长度为1的文件名,但这不能进行描述,因此我使用了临时文件。
dbenham

无需担心唯一的一行。通过使用/V带有搜索字符串的选项,您可以简单地查找不包含CR的行$。FINDSTR正则表达式$锚查找CR!另外,无需每次都计算文件名的长度。这可以在初始化期间完成,并且删除字符可以合并到字符串“ constant”中。
dbenham

74

您无需任何外部程序即可进行多色输出。

@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配置为以定义的颜色输出行号或文件名。
因此,我首先创建一个以文本为文件名的文件,内容为单个<backspace>字符(ASCII 8)。
然后,我在文件和nul中搜索所有非空行,因此文件名将以正确的颜色输出,并带有冒号,但是冒号将立即被删除<backspace>

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

@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

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


1
好的,这很好用,但是有什么办法可以减少键入到一行代码中的代码量呢?我是否可以将其设置为名为“ defcolor”的全局变量,并在每次打开命令提示符时都可以使用它?(通过导入还是将其作为系统变量?)
daniel11 2011年

1
你能给我看看我可以用的模板吗?像“ findstr”命令的模板一样,像“ FINDSTR / A / File [文件名] / Path [路径]”之类的东西,我可以用作以后使用的指南。
daniel11 2011年

1
@先生。Bungle:但是现在,所有其他角色也都可以使用了:-)
jeb 2012年

1
要移至换行符,请使用echo(
jeb

1
您应该在退出之前删除临时文件。del /f /q X;;)非常好的解决方法..
kodybrown 2015年

44

jeb编辑的答案几乎可以解决所有问题。但是以下字符串存在问题:

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

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

其他改进:

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

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

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

退格在换行符上不起作用,因此如果换行,该技术可能会出现问题。例如,如果控制台的线宽为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问答

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

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

只是为了好玩,我从琼·史塔克(Joan stark)的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 2013年

@Elieder-您尝试过吗?它应该可以工作,但是您需要在变量中获取适当的扩展ASCII代码,并且必须正确设置活动代码页。提出一个新的问题,如果您不能使其正常工作。
dbenham

我遇到了一个问题,我希望显示“ ##%76 space%##”,但是它的显示像是“ ## \。##”,我不知道为什么,下面是我的代码:“ call :c 0e“ ##”&call:c f9“%76 Spaces%”&call:c 0a“ ##”'
level42 2014年

似乎显示的外国字符是\ .. \':。并且它们显示在每一行上(这是隐藏的,因为我的内容是80 chr,我的窗口框架是80chr
level42

@ level42-窗口宽度必须比最长的线宽一点,因为它会写入不需要的字符,然后使用退格键来擦除它们。如果写入的内容超出了屏幕宽度,则退格键将无法再擦除它们。
dbenham 2014年

15

如果您使用的是现代Windows(已安装Powershell),则以下各项也可以正常工作

call :PrintBright Something Something

  (do actual batch stuff here)

call :PrintBright Done!
goto :eof


:PrintBright
powershell -Command Write-Host "%*" -foreground "White"

根据需要调整颜色。


好主意。我扩展了这个答案
rojo 2014年

7

dbenham的bird和语法skrebbel的powershellwrite-host方法结合使用,似乎powershell可以比dbenham的纯批处理方法更快地渲染复杂的艺术作品(嗯,无论如何,在对powershell进行一次底漆处理之后)。尽管我没有用鸟以外的任何东西进行测试,但是需要最小程度地按摩琴弦。例如,如果要使用亮绿色的传输结束字符,则可能不走运。 :)

此方法需要回显到临时文件,这仅仅是因为为每个调用powershellcall :c会花费很多时间,并且将输出排队一次进行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

结果:

在此处输入图片说明


7

没有外部工具。这是一个自编译的bat / .net混合文件(应另存为.BAT),可以在安装了.net框架的任何系统上使用(很少看到没有.NET框架的窗口,即使对于最旧的XP / 2003安装)。它使用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

您还可以检查carlos的颜色功能-> http://www.dostips.com/forum/viewtopic.php?f=3&t=4453



2


“ 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

3
我想QBasic自XP以来没有安装在任何现代Windows版本上
jeb 2012年


1

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

@回声关闭

chgcolor 03

echoj“嗨”

chgcolor 0d

echoj“世界”

chgcolor 07

echoj $ 0a

将文件另存为“ hi.bat”到桌面。现在打开命令提示符,导航到您的Desktop文件夹,然后键入“ hi.bat”(不带引号)。那应该使您开始一定要阅读两个网页以获得完整的教程。


1

如果您的控制台支持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.phptasklist ?p=6827#p6827 并使用它可以测试将哪些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

1

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

在命令提示符中:

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

回声Ctrl+ [[32m HI Ctrl+[[0mEnter

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

[32m  HI  [0m

0

在我的上一个答案因未包含代码而被删除后,由于堆栈溢出无法显示所使用的Ansi字符,从而使代码的存在变得毫无意义(鉴于基于它们的代码),我重新设计了代码以包含填充转义符的方法,详细信息如下 @Sam Hasler填充方法

在此过程中,我还取出了支持宏的所有子例程,并调整了我的方法,以将参数传递给宏。

所有宏都平衡Setlocal / Endlocal对,以防止^&^& endlocal在完成对Arg的处理后通过使用来超过递归级别。

std.out宏还演示了如何调整宏以将输出存储到可以通过Endlocal屏障生存的变量中。

@Echo off & Mode 1000

::: / Creates two variables with one character DEL=Ascii-08 and /AE=Ascii-27 escape code. only /AE is used
::: - http://www.dostips.com/forum/viewtopic.php?t=1733
::: - https://stackoverflow.com/a/34923514/12343998
:::
::: - DEL and ESC can be used  with and without DelayedExpansion, except during Macro Definition
    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 "/AE=%%b"
    )
::: \

::: / Establish Environment for macro Definition
    Setlocal DisableDelayedExpansion

    (Set LF=^


    %= NewLine =%)

    Set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"
::: \

::: / Ascii code variable assignment
::: - Variables used for cursor Positiong Ascii codes in the form of bookends to prevent ansi escape code disrupting macro definition
    Set "[=%/AE%["
    Set "]=H"
::: - define Variables for Ascii color code values
    Set "Red=%/AE%[31m"
    Set "Green=%/AE%[32m"
    Set "Yellow=%/AE%[33m"
    Set "Blue=%/AE%[34m"
    Set "Purple=%/AE%[35m"
    Set "Cyan=%/AE%[36m"
    Set "White=%/AE%[37m"
    Set "Grey=%/AE%[90m"
    Set "Pink=%/AE%[91m"
    Set "BrightGreen=%/AE%[92m"
    Set "Beige=%/AE%[93m"
    Set "Aqua=%/AE%[94m"
    Set "Magenta=%/AE%[95m"
    Set "Teal=%/AE%[96m"
    Set "BrightWhite=%/AE%[97m"
    Set "Off=%/AE%[0m"
::: \

::: / mini-Macro to Pseudo pipe complex strings into Macros.
    Set "Param|=Set Arg-Output="
::: \

::: / Macro for outputing to cursor position Arg1 in color Arg2
    Set Pos.Color=^&for /L %%n in (1 1 2) do if %%n==2 (%\n%
        For /F "tokens=1,2 delims=, " %%G in ("!argv!") do (%\n%
            Echo(![!%%G!]!!%%H!!Arg-Output!!Off!^&^&Endlocal%\n%
        ) %\n%
    ) ELSE setlocal enableDelayedExpansion ^& set argv=, 
::: \

::: / Macro variable for creating a Colored prompt with pause at Cursor pos Arg1 in Color Arg2
    Set Prompt.Pause=^&for /L %%n in (1 1 2) do if %%n==2 (%\n%
        For /F "tokens=1,2 delims=, " %%G in ("!argv!") do (%\n%
        Echo.!/AE![%%G!]!!/AE![%%Hm!Arg-Output!!Off!%\n%
        pause^>nul ^&^& Endlocal%\n%
        ) %\n%
    ) ELSE setlocal enableDelayedExpansion ^& set argv=, 
::: \

::: / Macro variable for outputing to stdout on a new line with selected color Arg1 and store output to VarName Arg2
    Set std.out=^&for /L %%n in (1 1 2) do if %%n==2 (%\n%
        For /F "tokens=1,2 delims=, " %%G in ("!argv!") do (%\n%
        Echo.!/AE![%%Gm!Arg-Output!!Off!^&^& Endlocal ^&(Set %%H=!Arg-Output!)%\n%
        ) %\n%
    ) ELSE setlocal enableDelayedExpansion ^& set argv=, 
::: \

::: / Stringlength Macro. Not utilized in this example.
::: Usage: %Param|%string or expanded variable%get.strLen% ResultVar
Set get.strLen=^&for /L %%n in (1 1 2) do if %%n==2 (%\n%
    For /F "tokens=1,* delims=, " %%G in ("!argv!") do (%\n%
        Set tmpLen=!Arg-Output!%\n%
        Set LenTrim=Start%\n%
        For /L %%a in (1,1,250) Do (%\n%
            IF NOT "!LenTrim!"=="" (%\n%
                Set LenTrim=!tmpLen:~0,-%%a!%\n%
                If "!LenTrim!"=="" Echo.>nul ^&^& Endlocal ^&(Set %%G=%%a)%\n%
            )%\n%
        ) %\n%
    ) %\n%
) ELSE setlocal enableDelayedExpansion ^& set argv=, 
::: \


::: / Create Script break for Subroutines. Subroutines not utilized in this example
    Goto :main
::: \

::: / Subroutines

::: \

::: / Script main Body
:::::: - Example usage
:main

    Setlocal EnableDelayedExpansion

For %%A in ("31,1,37" "41,1,47" "90,1,97" "100,1,107") do For /L %%B in (%%~A) Do %Param|%[Color Code = %%B.]%std.out% %%B AssignVar

        Set "XP=20"
    For %%A in (red aqua white brightwhite brightgreen beige blue magenta green pink cyan grey yellow purple teal) do (
        Set /A XP+=1
        Set /A YP+=1
        Set "output=%%A !YP!;!XP!"
        %Param|%Cursor Pos: !YP!;!XP!, %%A %Pos.Color% !YP!;!XP! %%A
    )
    %Param|%Example %green%Complete.%prompt.pause% 32;10 31

    Endlocal

Exit /B
::: \ End Script

感谢@Martijn Pieters删除了我之前的答案。在重写代码时,我还亲自发现了一些操纵宏的新方法。

脚本输出


0

Jebs解决方案的另一种改编版本,通过使用宏参数和变量替换避免了调用的使用:

@Echo off
 :# Macro Definitions
    For /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (set "DEL=%%a")
 :# %\C% - Color macro; No error checking. Usage:
 :# %\C:?=HEXVALUE%Output String
 :# (%\C:?=HEXVALUE%Output String) & (%\C:?=HEXVALUE%Output String)
    Set "\C=For %%o in (1 2)Do if %%o==2 (( <nul set /p ".=%DEL%" > "^^!os:\n=^^!" ) & ( findstr /v /a:? /R "^$" "^^!os:\n=^^!" nul ) & ( del "^^!os:\n=^^!" > nul 2>&1 ) & (Set "testos=^^!os:\n=^^!" & If not "^^!testos^^!" == "^^!os^^!" (Echo/)))Else Set os="
 :# Ensure macro escaping is correct depending on delayedexpansion environment type
    If Not "!![" == "[" (
     Set "\C=%\C:^^=^%"
    )
    Setlocal EnableExtensions EnableDelayedExpansion
    PUSHD "%~dp0"
 :# SCRIPT MAIN BODY
 :# To force a new line; terminate an output string with: \n
 :# Usage info:
    (%\C:?=40% This is an example of usage\n)&(%\C:?=50% Trailing whitespace and periods are removed.\n)
    (%\C:?=0e% Leading spaces and periods are retained)&(%\C:?=e0%. NOT SUPPORTED - \n)
     %\C:?=02% Colon ^& Unescaped Ampersands ^& doublequotes\n
     %\C:?=02% LSS than ^& GTR than symbols ^& foreward and backward slashes\n
    (%\C:?=02% Pipe ^& Question Mark and Asterisk characters.\n) & (%\C:?=e2%^^! Exclaimation ^^! marks must be escaped\n)
:end
    POPD
    Endlocal
Goto :Eof
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.