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

发布于 2024-10-05 22:05:00 字数 294 浏览 1 评论 0原文

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

echo hi world

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

set color1= color 2
set color9= color A

然后将它们部署在同一行上,

echo hi world

但我不知道该怎么做。

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

I want "hi" to be one color, and "world" to be another color. Maybe I could set the COLOR command as a variable:

set color1= color 2
set color9= color A

and then deploy them both on the same line along with

echo hi world

but I don't know how I would do that.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

幸福%小乖 2024-10-12 22:05:00

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

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

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

@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

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

You can do multicolor outputs without any external programs.

@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

It uses the color feature of the findstr command.

Findstr can be configured to output line numbers or filenames in a defined color.
So I first create a file with the text as filename, and the content is a single <backspace> character (ASCII 8).
Then I search all non empty lines in the file and in nul, so the filename will be output in the correct color appended with a colon, but the colon is immediatly removed by the <backspace>.

EDIT: One year later ... all characters are valid

@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

This uses the rule for valid path/filenames.
If a \..\ is in the path the prefixed elemet will be removed completly and it's not necessary that this element contains only valid filename characters.

寻梦旅人 2024-10-12 22:05:00

jeb 编辑后的答案接近解决所有问题。但它在处理以下字符串时存在问题:

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

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

其他改进:

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

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

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

退格键无法跨越换行符,因此如果换行,该技术可能会出现问题。例如,如果控制台的行宽为 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

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

更新 2012-12-14

在 < a href="http://www.dostips.com/forum/viewtopic.php?f=3&t=4014" rel="noreferrer">DosTips 和 SS64。事实证明,如果在命令行上提供,FINDSTR 也会损坏包含扩展 ASCII 的文件名。我更新了我的 FINDSTR 问答

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

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

只是为了好玩,我从 joan stark 的 ASCII Art Gallery 并将其改编为与 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

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"
<nul >"%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
    <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
胡大本事 2024-10-12 22:05:00

实际上,这可以在不创建临时文件的情况下完成。
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。我的输出有问题!您在上一个示例中没有的字符。 (或者至少你没有出现相同的症状。)有待调查。

Actually this can be done without creating a temporary file.
The method described by jeb and dbenham will work even with a target file that contains no backspaces. The critical point is that the line recognized by findstr.exe must not end with a CRLF.
So the obvious text file to scan with a line not ending with a CRLF is the invoking batch itself, provided that we end it with such a line!
Here's an updated example script working this way...

Changes from the previous example:

  • Uses a single dash on the last line as the searchable string. (Must be short and not appear anywhere else like this in the batch.)
  • Renamed routines and variables to be a little more object-oriented :-)
  • Removed one call level, to slightly improve performance.
  • Added comments (Beginning with :# to look more like most other scripting languages.)

@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. I'm having a problem with the output of the ! character that you did not have in the previous example. (Or at least you did not have the same symptoms.) To be investigated.

执妄 2024-10-12 22:05:00

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

call :PrintBright Something Something

  (do actual batch stuff here)

call :PrintBright Done!
goto :eof


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

根据您的需要调整颜色。

If you have a modern Windows (that has powershell installed), the following may work fine as well

call :PrintBright Something Something

  (do actual batch stuff here)

call :PrintBright Done!
goto :eof


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

Adjust the color as you see fit.

愿得七秒忆 2024-10-12 22:05:00

dbenham 的鸟和语法结合起来skrebbel 的 powershell write-host 方法,看起来 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

结果:

在此处输入图像描述

Combining dbenham's bird and syntax with skrebbel's powershell write-host method, it seems that powershell can render complex art more quickly than dbenham's pure batch method (well, after powershell has been primed once, anyway). Minimal massaging of the strings are needed, although I haven't tested this with anything other than the bird. If you want a bright green end-of-transmission character for example, you may be out of luck. :)

This method requires echoing out to a temp file, simply because invoking powershell for each call :c takes forever, and it's much faster to queue the output for one powershell invocation. But it does have the advantage of simplicity and efficiency.

@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

Result:

enter image description here

无需外部工具。这是一个自我-编译的bat/.net混合(应保存为.BAT),可以在任何安装了.net框架的系统上使用(很少见到即使对于最旧的 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

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

Without external tools.This is a self-compiled bat/.net hybrid (should be saved as .BAT) that can be used on any system that have installed .net framework (it's a rare thing to see an windows without .NET framework even for the oldest XP/2003 installations) . It uses jscript.net compiler to create an exe capable to print strings with different background/foreground color only for the current line.

@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;

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

You can also check carlos' color function -> http://www.dostips.com/forum/viewtopic.php?f=3&t=4453

美羊羊 2024-10-12 22:05:00

是的,可以使用 cmdcolor

echo \033[32mhi \033[92mworld

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

Yes, it is possible with cmdcolor:

echo \033[32mhi \033[92mworld

hi will be dark green, and world - light green.

往日 2024-10-12 22:05:00

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

在命令提示符中:

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

echo Ctrl+[[32m HI Ctrl+[ [0mEnter

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

[32m  HI  [0m

Windows 10 ((Version 1511, build 10586, release 2015-11-10)) supports ANSI colors.
You can use the escape key to trigger the color codes.

In the Command Prompt:

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

echo Ctrl+[[32m HI Ctrl+[[0mEnter

When using a text editor, you can use ALT key codes.
The ESC key code can be created using ALT and NUMPAD numbers : Alt+027

[32m  HI  [0m
南街女流氓 2024-10-12 22:05:00

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

使用 ANSI_escape_code.SGR_parameters

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

I'll give you the answer you're looking for first, for those who don't want to read a bunch of explanations.

use ANSI_escape_code.SGR_parameters

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

???? Do not forget input ESC0x1B (Hex), \033 (Oct), 27(Dec) Virtual-Key Codes VK_ESCAPE

I suggest you copy (in case you are missing the ESC key) the above contents, and then paste it on the notepad++ or others IDE you like.

output as below picture

enter image description here

Explanation

according ANSI_escape_code.SGR_parameters you know

NumberNameNoteExample
0Reset or normalAll attributes offESC[0m or ESC[m
1Bold or increased intensityESC[1m
3ItalicESC[3m
4UnderlineESC[4m
8Conceal or hideNot widely supported.ESC[8m
30–37Set foreground color30:black 31: red, 32: green, 33: yellow, 34: blue, 35: purple, 36: Aqua, 37: whitered: ESC[31m
38Set foreground colorNext arguments are 5;n or 2;r;g;bred: ESC[38m;2;255;0;0m
40–47Set background colorred: ESC[41m
48Set background colorNext arguments are 5;n or 2;r;g;bred: ESC[48m;2;255;0;0m

Of course, there are many more you can go to see.

for example,

Fake codecode (copy this to try by yourself)demo
ESC[31mESC[4mfore color: red and style:underlineESC[0mecho [31m[4mfore color: red and style:underline[0mfore-color:red and underline
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

where ESC = 0x1B (since typing ESC in here, the user can't see it.)

Script and Exercises

@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

output:

enter image description here

原谅过去的我 2024-10-12 22:05:00

中涵盖了几种方法
“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

Several methods are covered in
"51} How can I echo lines in different colors in NT scripts?"
http://www.netikka.net/tsneti/info/tscmd051.htm

One of the alternatives: If you can get hold of QBASIC, using colors is relatively easy:

  @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
笨死的猪 2024-10-12 22:05:00

如果您的控制台支持 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

If your console supports ANSI colour codes (e.g. ConEmu, Clink or ANSICON) you can do this:

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

where ESC variable contains ASCII character 27.

I found a way to populate the ESC variable here: http://www.dostips.com/forum/viewtopic.php?p=6827#p6827
and using tasklist it's possible to test what DLLs are loaded into a process.

The following script gets the process ID of the cmd.exe that the script is running in. Checks if it has a dll that will add ANSI support injected, and then sets colour variables to contain escape sequences or be empty depending on whether colour is supported or not.

@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
凑诗 2024-10-12 22:05:00

您应该从以下位置下载 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 目录。这将允许它们从命令行执行。
打开记事本并将以下内容复制到其中:

@回声关闭

更改颜色03

回显“嗨”

更改颜色 0d

回显“世界”

更改颜色07

回显 $0a

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

You should download chgcolor.zip from
http://www.mailsend-online.com/blog/setting-text-color-in-a-batch-file.html
and also download echoj.zip from
www.mailsend-online.com/blog/?p=41
They're both towards the bottom of the page.
Extract both folders to the desktop
and copy the executables(.exe files) from inside the extracted folders to the C:\Windows directory. This will allow them to be executed from the command line.
Open up notepad and copy the following into it:

@echo off

chgcolor 03

echoj "hi "

chgcolor 0d

echoj "world"

chgcolor 07

echoj $0a

Save the file to the Desktop as hi.bat. Now open the command prompt and navigate to your Desktop folder and type "hi.bat" without the quotes. That should get you started besure to read both webpages to get a full tutorial.

坏尐絯℡ 2024-10-12 22:05:00

我喜欢@jeb发布的函数方法,但他的(第二个)解决方案有一些小问题:

  • X文件没有被删除,
  • 如果文件夹中存在,任何X文件都会被覆盖
  • “^”字符实际上不起作用
  • 没有换行符在彩色“回声”之后
  • 测试bat文件后没有暂停

这就是为什么我想分享我对这些问题的解决方案,而不是请求侵入性编辑。

@echo off

call :colorEcho 1a "a"
call :colorEcho 1b "b"
call :colorEcho 1c "^!<>:&| %%%%"*?"
echo.
pause
exit /b

:colorEcho
    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"
    )
    set "param=^%~2" !
    set "param=!param:"=\"!"
    rem Prepare a file "æ" with only one dot
    <nul > æ set /p ".=."
    findstr /p /A:%1 "." "!param!\..\æ" nul
    <nul set /p ".=%DEL%%DEL%%DEL%%DEL%%DEL%%DEL%%DEL%"
    rem Delete "æ" file
    del æ
    echo.
    endlocal
    exit /b

与@jeb one相比,对该脚本的评论:

  • X文件现在被命名为“æ”,它不太可能存在
  • 这个“æ”文件在调用该函数后被删除
  • 现在允许“^”字符
  • 换行符在每次函数调用后添加(如果需要,您可以将其删除)
  • 最后的暂停让您有机会更好地测试此代码。

I liked the function approach posted by @jeb but there are a few small issues with his (second) solution:

  • the X file is not deleted
  • any X file is overwritten if present in the folder
  • the '^' character is not actually working
  • no newline after the colored "echo"
  • no pause after test bat file

That is why I feel to share my solution to these issues, insted of requesting an invasive edit.

@echo off

call :colorEcho 1a "a"
call :colorEcho 1b "b"
call :colorEcho 1c "^!<>:&| %%%%"*?"
echo.
pause
exit /b

:colorEcho
    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"
    )
    set "param=^%~2" !
    set "param=!param:"=\"!"
    rem Prepare a file "æ" with only one dot
    <nul > æ set /p ".=."
    findstr /p /A:%1 "." "!param!\..\æ" nul
    <nul set /p ".=%DEL%%DEL%%DEL%%DEL%%DEL%%DEL%%DEL%"
    rem Delete "æ" file
    del æ
    echo.
    endlocal
    exit /b

Comments to this script in comparison to @jeb one:

  • the X file is now named "æ", which is more unlikely to exist
  • this "æ" file is removed after the function is called
  • the '^' character is now permitted
  • a newline is added after every function call (you can remove it if you want)
  • a final pause gives you the opportunity to better test this code.
↙温凉少女 2024-10-12 22:05:00

虚拟终端代码使用的宏解决方案对于 Windows 10 用户

对于 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://learn.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

Parrot

A macro solution for virtual terminal code usage for windows 10 users

For windows 10 users, it is the fastest method outside of using VT sequences directly while of being more readable.

::: 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://learn.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

Parrot

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文