如何在 Windows 批处理文件中有多种颜色?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4339649/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to have multiple colors in a Windows batch file?
提问by daniel11
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
我想知道是否有可能在 Windows 批处理文件的同一行上有不同颜色的文本,例如,如果它说
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:
我希望“hi”是一种颜色,“world”是另一种颜色。也许我可以将 COLOR 命令设置为变量:
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.
但我不知道我会怎么做。
采纳答案by JFL
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...
实际上,这可以在不创建临时文件的情况下完成。jeb 和 dbenham 描述的方法甚至可以用于不包含退格符的目标文件。关键点是 findstr.exe 识别的行不能以 CRLF 结尾。因此,要扫描的行不以 CRLF 结尾的明显文本文件是调用批处理本身,前提是我们以这样的行结尾!这是一个以这种方式工作的更新示例脚本......
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.
附注。我的输出有问题!您在上一个示例中没有的字符。(或者至少你没有相同的症状。)有待调查。
回答by jeb
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 命令的颜色功能。
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>
.
Findstr 可以配置为以定义的颜色输出行号或文件名。
所以我首先创建一个以文本为文件名的文件,内容为单个<backspace>
字符(ASCII 8)。
然后我在文件和 nul 中搜索所有非空行,因此文件名将以正确的颜色输出并附加冒号,但冒号会立即被<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.
这使用有效路径/文件名的规则。
如果 a\..\
在路径中,前缀 elemet 将被完全删除,并且此元素不必只包含有效的文件名字符。
回答by dbenham
jeb's edited answer comes close to solving all the issues. But it has problems with the following strings:
jeb 编辑后的答案几乎可以解决所有问题。但它有以下字符串的问题:
"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.
将 %TEMP% 位置用于临时文件,因此不再需要对当前目录的写访问权限。
创建了 2 个变体,一个是字符串文字,另一个是包含字符串的变量的名称。变量版本通常不太方便,但它消除了一些特殊的字符转义问题。
添加了 /n 选项作为可选的第三个参数,以在输出的末尾附加换行符。
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.
Backspace 不能跨越换行符,因此如果换行,该技术可能会出现问题。例如,如果控制台的线宽为 80,则打印长度在 74 - 79 之间的字符串将无法正常工作。
@echo off
setlocal
call :initColorPrint
call :colorPrint 0a "a"
call :colorPrint 0b "b"
set "txt=^" & call :colorPrintVar 0c txt
call :colorPrint 0d "<"
call :colorPrint 0e ">"
call :colorPrint 0f "&"
call :colorPrint 1a "|"
call :colorPrint 1b " "
call :colorPrint 1c "%%%%"
call :colorPrint 1d ^"""
call :colorPrint 1e "*"
call :colorPrint 1f "?"
call :colorPrint 2a "!"
call :colorPrint 2b "."
call :colorPrint 2c ".."
call :colorPrint 2d "/"
call :colorPrint 2e "\"
call :colorPrint 2f "q:" /n
echo(
set complex="c:\hello world!/.\..\a//^<%%>&|!" /^^^<%%^>^&^|!\
call :colorPrintVar 74 complex /n
call :cleanupColorPrint
exit /b
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:colorPrint Color Str [/n]
setlocal
set "str=%~2"
call :colorPrintVar %1 str %3
exit /b
:colorPrintVar Color StrVar [/n]
if not defined %~2 exit /b
setlocal enableDelayedExpansion
set "str=a%DEL%!%~2:\=a%DEL%\..\%DEL%%DEL%%DEL%!"
set "str=!str:/=a%DEL%/..\%DEL%%DEL%%DEL%!"
set "str=!str:"=\"!"
pushd "%temp%"
findstr /p /A:%1 "." "!str!\..\x" nul
if /i "%~3"=="/n" echo(
exit /b
:initColorPrint
for /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do set "DEL=%%a"
<nul >"%temp%\x" set /p "=%DEL%%DEL%%DEL%%DEL%%DEL%%DEL%.%DEL%"
exit /b
:cleanupColorPrint
del "%temp%\x"
exit /b
UPDATE 2012-11-27
更新 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
此方法在 XP 上失败,因为 FINDSTR 将退格键显示为屏幕上的句点。jeb 的原始答案适用于 XP,尽管存在已经指出的限制
UPDATE 2012-12-14
更新 2012-12-14
There has been a lot of development activity at DosTipsand 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.
DosTips和SS64有很多开发活动。事实证明,如果在命令行中提供,FINDSTR 也会损坏包含扩展 ASCII 的文件名。我已经更新了我的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.
下面是一个适用于 XP 的版本,支持除 0x00(空)、0x0A(换行)和 0x0D(回车)之外的所有单字节字符。但是,在 XP 上运行时,大多数控制字符将显示为点。这是 XP 上 FINDSTR 的固有特性,无法避免。
Unfortunately, adding support for XP and for extended ASCII characters slows the routine down :-(
不幸的是,添加对 XP 和扩展 ASCII 字符的支持会减慢例程:-(
Just for fun, I grabbed some color ASCII art from joan stark's ASCII Art Galleryand adapted it for use with ColorPrint. I added a :c entry point just for shorthand, and to handle an issue with quote literals.
只是为了好玩,我从joan stark 的 ASCII Art Gallery 中抓取了一些彩色 ASCII 艺术并将其改编为与 ColorPrint 一起使用。我添加了一个 :c 入口点只是为了速记,并处理引号文字的问题。
@echo off
setlocal disableDelayedExpansion
set q=^"
echo(
echo(
call :c 0E " , .-;" /n
call :c 0E " , |\ / / __," /n
call :c 0E " |\ '.`-.| |.'.-'" /n
call :c 0E " \`'-: `; : /" /n
call :c 0E " `-._'. \'|" /n
call :c 0E " ,_.-=` ` ` ~,_" /n
call :c 0E " '--,. "&call :c 0c ".-. "&call :c 0E ",=!q!." /n
call :c 0E " / "&call :c 0c "{ "&call :c 0A "* "&call :c 0c ")"&call :c 0E "`"&call :c 06 ";-."&call :c 0E "}" /n
call :c 0E " | "&call :c 0c "'-' "&call :c 06 "/__ |" /n
call :c 0E " / "&call :c 06 "\_,\|" /n
call :c 0E " | (" /n
call :c 0E " "&call :c 0c "__ "&call :c 0E "/ ' \" /n
call :c 02 " /\_ "&call :c 0c "/,'`"&call :c 0E "| ' "&call :c 0c ".-~!q!~~-." /n
call :c 02 " |`.\_ "&call :c 0c "| "&call :c 0E "/ ' , "&call :c 0c "/ \" /n
call :c 02 " _/ `, \"&call :c 0c "| "&call :c 0E "; , . "&call :c 0c "| , ' . |" /n
call :c 02 " \ `, "&call :c 0c "| "&call :c 0E "| , , "&call :c 0c "| : ; : |" /n
call :c 02 " _\ `, "&call :c 0c "\ "&call :c 0E "|. , "&call :c 0c "| | | | |" /n
call :c 02 " \` `. "&call :c 0c "\ "&call :c 0E "| ' "&call :c 0A "|"&call :c 0c "\_|-'|_,'\|" /n
call :c 02 " _\ `, "&call :c 0A "`"&call :c 0E "\ ' . ' "&call :c 0A "| | | | | "&call :c 02 "__" /n
call :c 02 " \ `, "&call :c 0E "| , ' "&call :c 0A "|_/'-|_\_/ "&call :c 02 "__ ,-;` /" /n
call :c 02 " \ `, "&call :c 0E "\ . , ' .| | | | | "&call :c 02 "_/' ` _=`|" /n
call :c 02 " `\ `, "&call :c 0E "\ , | | | | |"&call :c 02 "_/' .=!q! /" /n
call :c 02 " \` `, "&call :c 0E "`\ \/|,| ;"&call :c 02 "/' .=!q! |" /n
call :c 02 " \ `, "&call :c 0E "`\' , | ; "&call :c 02 "/' =!q! _/" /n
call :c 02 " `\ `, "&call :c 05 ".-!q!!q!-. "&call :c 0E "': "&call :c 02 "/' =!q! /" /n
call :c 02 " jgs _`\ ;"&call :c 05 "_{ ' ; "&call :c 02 "/' =!q! /" /n
call :c 02 " _\`-/__"&call :c 05 ".~ `."&call :c 07 "8"&call :c 05 ".'.!q!`~-. "&call :c 02 "=!q! _,/" /n
call :c 02 " __\ "&call :c 05 "{ '-."&call :c 07 "|"&call :c 05 ".'.--~'`}"&call :c 02 " _/" /n
call :c 02 " \ .=!q!` "&call :c 05 "}.-~!q!'"&call :c 0D "u"&call :c 05 "'-. '-..' "&call :c 02 "__/" /n
call :c 02 " _/ .!q! "&call :c 05 "{ -'.~('-._,.'"&call :c 02 "\_,/" /n
call :c 02 " / .!q! _/'"&call :c 05 "`--; ; `. ;" /n
call :c 02 " .=!q! _/' "&call :c 05 "`-..__,-'" /n
call :c 02 " __/'" /n
echo(
exit /b
:c
setlocal enableDelayedExpansion
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:colorPrint Color Str [/n]
setlocal
set "s=%~2"
call :colorPrintVar %1 s %3
exit /b
:colorPrintVar Color StrVar [/n]
if not defined DEL call :initColorPrint
setlocal enableDelayedExpansion
pushd .
':
cd \
set "s=!%~2!"
:: The single blank line within the following IN() clause is critical - DO NOT REMOVE
for %%n in (^"^
^") do (
set "s=!s:\=%%~n\%%~n!"
set "s=!s:/=%%~n/%%~n!"
set "s=!s::=%%~n:%%~n!"
)
for /f delims^=^ eol^= %%s in ("!s!") do (
if "!" equ "" setlocal disableDelayedExpansion
if %%s==\ (
findstr /a:%~1 "." "\'" nul
<nul set /p "=%DEL%%DEL%%DEL%"
) else if %%s==/ (
findstr /a:%~1 "." "/.\'" nul
<nul set /p "=%DEL%%DEL%%DEL%%DEL%%DEL%"
) else (
>colorPrint.txt (echo %%s\..\')
findstr /a:%~1 /f:colorPrint.txt "."
<nul set /p "=%DEL%%DEL%%DEL%%DEL%%DEL%%DEL%%DEL%"
)
)
if /i "%~3"=="/n" echo(
popd
exit /b
:initColorPrint
for /f %%A in ('"prompt $H&for %%B in (1) do rem"') do set "DEL=%%A %%A"
<nul >"%temp%\'" set /p "=."
subst ': "%temp%" >nul
exit /b
:cleanupColorPrint
2>nul del "%temp%\'"
2>nul del "%temp%\colorPrint.txt"
>nul subst ': /d
exit /b
回答by skrebbel
If you have a modern Windows (that has powershell installed), the following may work fine as well
如果你有一个现代的 Windows(安装了 powershell),下面的也可以正常工作
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.
调整您认为合适的颜色。
回答by npocmaka
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.
没有外部工具。这是一个自编译的bat/.net混合体(应该另存为.BAT
),可以在任何安装了.net框架的系统上使用(很少看到没有.NET框架的windows,即使是最旧的 XP/2003 安装)。它使用 jscript.net 编译器创建一个 exe,该 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;
Example coloroutput.bat -s "aa\nbb\n\u0025cc" -b 10 -f 3 -n -e
例子 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
您还可以检查卡洛斯的颜色功能 -> http://www.dostips.com/forum/viewtopic.php?f=3&t=4453
回答by rojo
Combining dbenham's bird and syntaxwith 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. :)
将dbenham 的小鸟和语法与skrebbel 的 powershellwrite-host
方法相结合,似乎 powershell 可以比 dbenham 的纯批处理方法更快地呈现复杂的艺术(好吧,无论如何,在 powershell 已经启动一次之后)。需要对琴弦进行最少的按摩,尽管我还没有用鸟以外的任何东西进行过测试。例如,如果你想要一个亮绿色的传输结束字符,你可能不走运。 :)
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.
此方法需要回显到临时文件,因为为每个调用 powershellcall :c
需要永远,并且将输出排队以进行一次 powershell 调用要快得多。但它确实具有简单和高效的优点。
@echo off
setlocal disableDelayedExpansion
set q=^"
echo(
echo(
call :c 0E " , .-;" /n
call :c 0E " , |\ / / __," /n
call :c 0E " |\ '.`-.| |.'.-'" /n
call :c 0E " \`'-: `; : /" /n
call :c 0E " `-._'. \'|" /n
call :c 0E " ,_.-=` ` ` ~,_" /n
call :c 0E " '--,. "&call :c 0c ".-. "&call :c 0E ",=!q!." /n
call :c 0E " / "&call :c 0c "{ "&call :c 0A "* "&call :c 0c ")"&call :c 0E "`"&call :c 06 ";-."&call :c 0E "}" /n
call :c 0E " | "&call :c 0c "'-' "&call :c 06 "/__ |" /n
call :c 0E " / "&call :c 06 "\_,\|" /n
call :c 0E " | (" /n
call :c 0E " "&call :c 0c "__ "&call :c 0E "/ ' \" /n
call :c 02 " /\_ "&call :c 0c "/,'`"&call :c 0E "| ' "&call :c 0c ".-~!q!~~-." /n
call :c 02 " |`.\_ "&call :c 0c "| "&call :c 0E "/ ' , "&call :c 0c "/ \" /n
call :c 02 " _/ `, \"&call :c 0c "| "&call :c 0E "; , . "&call :c 0c "| , ' . |" /n
call :c 02 " \ `, "&call :c 0c "| "&call :c 0E "| , , "&call :c 0c "| : ; : |" /n
call :c 02 " _\ `, "&call :c 0c "\ "&call :c 0E "|. , "&call :c 0c "| | | | |" /n
call :c 02 " \` `. "&call :c 0c "\ "&call :c 0E "| ' "&call :c 0A "|"&call :c 0c "\_|-'|_,'\|" /n
call :c 02 " _\ `, "&call :c 0A "`"&call :c 0E "\ ' . ' "&call :c 0A "| | | | | "&call :c 02 "__" /n
call :c 02 " \ `, "&call :c 0E "| , ' "&call :c 0A "|_/'-|_\_/ "&call :c 02 "__ ,-;` /" /n
call :c 02 " \ `, "&call :c 0E "\ . , ' .| | | | | "&call :c 02 "_/' ` _=`|" /n
call :c 02 " `\ `, "&call :c 0E "\ , | | | | |"&call :c 02 "_/' .=!q! /" /n
call :c 02 " \` `, "&call :c 0E "`\ \/|,| ;"&call :c 02 "/' .=!q! |" /n
call :c 02 " \ `, "&call :c 0E "`\' , | ; "&call :c 02 "/' =!q! _/" /n
call :c 02 " `\ `, "&call :c 05 ".-!q!!q!-. "&call :c 0E "': "&call :c 02 "/' =!q! /" /n
call :c 02 " jgs _`\ ;"&call :c 05 "_{ ' ; "&call :c 02 "/' =!q! /" /n
call :c 02 " _\`-/__"&call :c 05 ".~ `."&call :c 07 "8"&call :c 05 ".'.!q!`~-. "&call :c 02 "=!q! _,/" /n
call :c 02 " __\ "&call :c 05 "{ '-."&call :c 07 "|"&call :c 05 ".'.--~'`}"&call :c 02 " _/" /n
call :c 02 " \ .=!q!` "&call :c 05 "}.-~!q!'"&call :c 0D "u"&call :c 05 "'-. '-..' "&call :c 02 "__/" /n
call :c 02 " _/ .!q! "&call :c 05 "{ -'.~('-._,.'"&call :c 02 "\_,/" /n
call :c 02 " / .!q! _/'"&call :c 05 "`--; ; `. ;" /n
call :c 02 " .=!q! _/' "&call :c 05 "`-..__,-'" /n
call :c 02 " __/'" /n
if exist "%temp%\color.psm1" (
powershell -command "&{set-executionpolicy remotesigned; Import-Module '%temp%\color.psm1'}"
del "%temp%\color.psm1"
)
echo(
exit /b
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:c <color pair> <string> </n>
setlocal enabledelayedexpansion
set "colors=0-black;1-darkblue;2-darkgreen;3-darkcyan;4-darkred;5-darkmagenta;6-darkyellow;7-gray;8-darkgray;9-blue;a-green;b-cyan;c-red;d-magenta;e-yellow;f-white"
set "p=%~1"
set "bg=!colors:*%p:~0,1%-=!"
set bg=%bg:;=&rem.%
set "fg=!colors:*%p:~-1%-=!"
set fg=%fg:;=&rem.%
if not "%~3"=="/n" set "br=-nonewline"
set "str=%~2" & set "str=!str:'=''!"
>>"%temp%\color.psm1" echo write-host '!str!' -foregroundcolor '%fg%' -backgroundcolor '%bg%' %br%
endlocal
Result:
结果:
回答by Alec Mev
回答by Timo Salmi
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
“51} 如何在 NT 脚本中回显不同颜色的行?”中介绍了几种方法。
http://www.netikka.net/tsneti/info/tscmd051.htm
One of the alternatives: If you can get hold of QBASIC, using colors is relatively easy:
备选方案之一:如果你能掌握 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
回答by A Smith
You should download chgcolor.zip from http://www.mailsend-online.com/blog/setting-text-color-in-a-batch-file.htmland 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:
您应该从 http://www.mailsend-online.com/blog/setting-text-color-in-a-batch-file.html下载 chgcolor.zip 并从 www.mailsend-online.com 下载 echoj.zip /blog/?p=41 它们都在页面底部。将两个文件夹解压缩到桌面,然后将解压缩文件夹中的可执行文件(.exe 文件)复制到 C:\Windows 目录。这将允许它们从命令行执行。打开记事本,将以下内容复制进去:
@echo off
chgcolor 03
echoj "hi "
chgcolor 0d
echoj "world"
chgcolor 07
echoj $0a
@回声关闭
更改颜色 03
回声“嗨”
更改颜色 0d
回声“世界”
更改颜色 07
回声$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.
将文件作为 hi.bat 保存到桌面。现在打开命令提示符并导航到您的桌面文件夹并键入不带引号的“hi.bat”。这应该让您开始阅读这两个网页以获得完整的教程。
回答by Sam Hasler
If your console supports ANSI colour codes (e.g. ConEmu, Clinkor ANSICON) you can do this:
如果您的控制台支持 ANSI 颜色代码(例如ConEmu、Clink或ANSICON),您可以这样做:
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.
其中 ESC 变量包含 ASCII 字符 27。
I found a way to populate the ESC variable here: http://www.dostips.com/forum/viewtopic.php?p=6827#p6827and using tasklist
it's possible to test what DLLs are loaded into a process.
我在这里找到了一种填充 ESC 变量的方法:http: //www.dostips.com/forum/viewtopic.phptasklist
?p=6827#p6827
并使用它可以测试哪些 DLL 加载到进程中。
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.
以下脚本获取运行该脚本的 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