我知道color bf命令设置了整个命令行窗口的颜色,但我想打印不同颜色的单行。


当前回答

为了让它在Windows 10上工作,你可以启用这个标志:ENABLE_VIRTUAL_TERMINAL_PROCESSING。

使用此注册表项,您可以默认设置此项

[HKCU\Console] VirtualTerminalLevel dword 0x1 .使用实例

其他回答

可以使用color命令更改整个控制台的颜色

Color 0F

是黑白的

Color 0A 

是黑色和绿色的

这不是一个很好的答案,但如果你知道目标工作站有Powershell,你可以这样做(假设BAT / CMD脚本):

CALL:ECHORED "Print me in red!"

:ECHORED
%Windir%\System32\WindowsPowerShell\v1.0\Powershell.exe write-host -foregroundcolor Red %1
goto:eof

编辑:(现在更简单了!)

这是一个老答案,但我想我要澄清和简化一点

PowerShell现在包含在从7开始的所有版本的Windows中。因此,这个答案的语法可以缩短为一种更简单的形式:

路径不需要指定,因为它应该已经在环境变量中。 明确的命令可以缩写。例如,你可以: 使用-fore代替-foregroundcolor 使用-back代替-backgroundcolor 这个命令也可以在“内联”中代替echo (而不是像上面那样创建一个单独的批处理文件)。


例子:

powershell write-host -fore Cyan This is Cyan text
powershell write-host -back Red This is Red background

更多信息:

完整的颜色列表和更多信息可在 - PowerShell Write-Host文档

为了让它在Windows 10上工作,你可以启用这个标志:ENABLE_VIRTUAL_TERMINAL_PROCESSING。

使用此注册表项,您可以默认设置此项

[HKCU\Console] VirtualTerminalLevel dword 0x1 .使用实例

I'm adding an answer to address an issue noted in some comments above: that inline ansi color codes can misbehave when inside a FOR loop (actually, within any parenthesized block of code). The .bat code below demonstrates (1) the use of inline color codes, (2) the color failure that can occur when inline color codes are used in a FOR loop or within a parenthesized block of code, and (3) a solution to the problem. When the .bat code executes, tests 2 and 3 demonstrate the colorcode failure, and test 4 shows no failure because it implements the solution.

[编辑2020-04-07:我发现了另一个解决方案,可能比调用子例程更有效。将FINDSTR短语括在括号中,如下所示:

   echo success | (findstr /R success)

ENDEDIT]

注意:根据我的(有限的)经验,颜色代码问题只有在输入被管道输送到代码块中的FINDSTR之后才会出现。这就是下面的.bat重现问题的方式。颜色代码问题可能比输送到FINDSTR之后更普遍。如果有人能解释问题的本质,如果有更好的解决方法,我会很感激。

@goto :main
:resetANSI
EXIT /B
rem  The resetANSI subroutine is used to fix the colorcode
rem  bug, even though it appears to do nothing.

:main
@echo off
setlocal EnableDelayedExpansion

rem  Define some useful colorcode vars:
for /F "delims=#" %%E in ('"prompt #$E# & for %%E in (1) do rem"') do set "ESCchar=%%E"
set "green=%ESCchar%[92m"
set "yellow=%ESCchar%[93m"
set "magenta=%ESCchar%[95m"
set "cyan=%ESCchar%[96m"
set "white=%ESCchar%[97m"
set "black=%ESCchar%[30m"

echo %white%Test 1 is NOT in a FOR loop nor within parentheses, and color works right.
   echo %yellow%[Test 1] %green%This is Green, %magenta%this is Magenta, and %yellow%this is Yellow.
   echo %Next, the string 'success' will be piped to FINDSTR...
   echo success | findstr /R success
   echo %magenta%This is magenta and FINDSTR found and displayed 'success'.%yellow%
   echo %green%This is green.
echo %cyan%Test 1 completed.

echo %white%Test 2 is within parentheses, and color stops working after the pipe to FINDSTR.
(  echo %yellow%[Test 2] %green%This is Green, %magenta%this is Magenta, and %yellow%this is Yellow.
   echo %Next, the string 'success' will be piped to FINDSTR...
   echo success | findstr /R success
   echo %magenta%This is supposed to be magenta and FINDSTR found and displayed 'success'.
   echo %green%This is supposed to be green.
)
echo %cyan%Test 2 completed.

echo %white%Test 3 is within a FOR loop, and color stops working after the pipe to FINDSTR.
for /L %%G in (3,1,3) do (
   echo %yellow%[Test %%G] %green%This is Green, %magenta%this is Magenta, and %yellow%this is Yellow.
   echo %Next, the string 'success' will be piped to FINDSTR...
   echo success | findstr /R success
   echo %magenta%This is supposed to be magenta and FINDSTR found and displayed 'success'.
   echo %green%This is supposed to be green.
)
echo %cyan%Test 3 completed.

echo %white%Test 4 is in a FOR loop but color works right because subroutine :resetANSI is 
echo called after the pipe to FINDSTR, before the next color code is used.
for /L %%G in (4,1,4) do (
   echo %yellow%[Test %%G] %green%This is Green, %magenta%this is Magenta, and %yellow%this is Yellow.
   echo %Next, the string 'success' will be piped to FINDSTR...
   echo success | findstr /R success
   call :resetANSI
   echo %magenta%This is magenta and FINDSTR found and displayed 'success'.
   echo %green%This is green.
)
echo %cyan%Test 4 completed.%white%

EXIT /B

自Windows XP以来,通过使用PowerShell作为通过命名管道链接到控制台输出的子进程,可以快速有效地用cmd批处理着色。这也可以用FindStr来完成,但是PowerShell提供了更多的选项,而且似乎更快。

保持PowerShell为子进程,使用管道进行通信的主要好处是,显示要比为每一行显示启动PowerShell或FindStr快得多。

其他优点:

不需要临时文件 通过管道进行回显允许显示完整的ASCII表而不需要转义。 与fd重定向工作良好。以stderr为例,或者重定向到一个文件/其他进程。

下面是一个示例代码:

::
:: Launch a PowerShell child process in the background linked to the console and 
:: earing through named pipe PowerShellCon_%PID%
::
:: Parameters :
::   [ PID ] : Console Process ID used as an identifier for the named pipe, launcher PID by default.
::   [ timeout ] : Subprocess max life in seconds, 300 by default. If -1, the subprocess
::                  will not terminate while the process %PID% is still alive.
:: Return :
::   0 if the child PowerShell has been successfully launched and the named pipe is available.
::   1 if it fails.
::   2 if we can't get a PID.
::   3 if PowerShell is not present or doesn't work.
::
:LaunchPowerShellSubProcess
  SET LOCALV_PID=
  SET LOCALV_TIMEOUT=300
  IF NOT "%~1" == "" SET LOCALV_PID=%~1
  IF NOT "%~2" == "" SET LOCALV_TIMEOUT=%~2
  powershell -command "$_" 2>&1 >NUL
  IF NOT "!ERRORLEVEL!" == "0" EXIT /B 3
  IF "!LOCALV_PID!" == "" (
    FOR /F %%P IN ('powershell -command "$parentId=(Get-WmiObject Win32_Process -Filter ProcessId=$PID).ParentProcessId; write-host (Get-WmiObject Win32_Process -Filter ProcessId=$parentId).ParentProcessId;"') DO (
      SET LOCALV_PID=%%P
    )
  )
  IF "!LOCALV_PID!" == "" EXIT /B 2
  START /B powershell -command "$cmdPID=$PID; Start-Job -ArgumentList $cmdPID -ScriptBlock { $ProcessActive = $true; $timeout=!LOCALV_TIMEOUT!; while((!LOCALV_TIMEOUT! -eq -1 -or $timeout -gt 0) -and $ProcessActive) { Start-Sleep -s 1; $timeout-=1; $ProcessActive = Get-Process -id !LOCALV_PID! -ErrorAction SilentlyContinue; } if ($timeout -eq 0 -or ^! $ProcessActive) { Stop-Process -Id $args; } } | Out-Null ; $npipeServer = new-object System.IO.Pipes.NamedPipeServerStream('PowerShellCon_!LOCALV_PID!', [System.IO.Pipes.PipeDirection]::In); Try { $npipeServer.WaitForConnection(); $pipeReader = new-object System.IO.StreamReader($npipeServer); while(($msg = $pipeReader.ReadLine()) -notmatch 'QUIT') { $disp='write-host '+$msg+';'; invoke-expression($disp); $npipeServer.Disconnect(); $npipeServer.WaitForConnection(); }; } Finally { $npipeServer.Dispose(); }" 2>NUL
  SET /A LOCALV_TRY=20 >NUL
  :LaunchPowerShellSubProcess_WaitForPipe
  powershell -nop -c "& {sleep -m 50}"
  SET /A LOCALV_TRY=!LOCALV_TRY! - 1 >NUL
  IF NOT "!LOCALV_TRY!" == "0" cmd /C "ECHO -NoNewLine|MORE 1>\\.\pipe\PowerShellCon_!LOCALV_PID!" 2>NUL || GOTO:LaunchPowerShellSubProcess_WaitForPipe
  IF "!LOCALV_TRY!" == "0" EXIT /B 1
  EXIT /B 0

这个“代码”是用延迟展开ON编写的,但可以重写为没有它的情况下工作。有很多安全要点需要考虑,不要在野外直接使用。

如何使用:

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS
IF ERRORLEVEL 1 (
  ECHO Extension inapplicable
  EXIT /B 1
)
::
SETLOCAL ENABLEDELAYEDEXPANSION
IF ERRORLEVEL 1 (
  ECHO Expansion inapplicable
  EXIT /B 1
)
CALL:LaunchPowerShellSubProcess
IF NOT ERRORLEVEL 0 EXIT /B 1
CALL:Color Cyan "I write this in Cyan"
CALL:Blue "I write this in Blue"
CALL:Green "And this in green"
CALL:Red -nonewline "And mix Red"
CALL:Yellow "with Yellow"
CALL:Green "And not need to trouble with ()<>&|;,%""^ and so on..."
EXIT /B 0
:Color
ECHO -foregroundcolor %*>\\.\pipe\PowerShellCon_!LOCALV_PID!
ECHO[|SET /P=>NUL
GOTO:EOF
:Blue
ECHO -foregroundcolor Blue %*>\\.\pipe\PowerShellCon_!LOCALV_PID!
ECHO[|SET /P=>NUL
GOTO:EOF
:Green
ECHO -foregroundcolor Green %*>\\.\pipe\PowerShellCon_!LOCALV_PID!
ECHO[|SET /P=>NUL
GOTO:EOF
:Red
ECHO -foregroundcolor Red %*>\\.\pipe\PowerShellCon_!LOCALV_PID!
ECHO[|SET /P=>NUL
GOTO:EOF
:Yellow
ECHO -foregroundcolor Yellow %*>\\.\pipe\PowerShellCon_!LOCALV_PID!
ECHO[|SET /P=>NUL
GOTO:EOF
::
:: Launch a PowerShell child process in the background linked to the console and 
:: earing through named pipe PowerShellCon_%PID%
::
:: Parameters :
::   [ PID ] : Console Process ID used as an identifier for the named pipe, launcher PID by default.
::   [ timeout ] : Subprocess max life in seconds, 300 by default. If -1, the subprocess
::                  will not terminate while the process %PID% is still alive.
:: Return :
::   0 if the child PowerShell has been successfully launched and the named pipe is available.
::   1 if it fails.
::   2 if we can't get a PID.
::   3 if PowerShell is not present or doesn't work.
::
:LaunchPowerShellSubProcess
  SET LOCALV_PID=
  SET LOCALV_TIMEOUT=300
  IF NOT "%~1" == "" SET LOCALV_PID=%~1
  IF NOT "%~2" == "" SET LOCALV_TIMEOUT=%~2
  powershell -command "$_" 2>&1 >NUL
  IF NOT "!ERRORLEVEL!" == "0" EXIT /B 3
  IF "!LOCALV_PID!" == "" (
    FOR /F %%P IN ('powershell -command "$parentId=(Get-WmiObject Win32_Process -Filter ProcessId=$PID).ParentProcessId; write-host (Get-WmiObject Win32_Process -Filter ProcessId=$parentId).ParentProcessId;"') DO (
      SET LOCALV_PID=%%P
    )
  )
  IF "!LOCALV_PID!" == "" EXIT /B 2
  START /B powershell -command "$cmdPID=$PID; Start-Job -ArgumentList $cmdPID -ScriptBlock { $ProcessActive = $true; $timeout=!LOCALV_TIMEOUT!; while((!LOCALV_TIMEOUT! -eq -1 -or $timeout -gt 0) -and $ProcessActive) { Start-Sleep -s 1; $timeout-=1; $ProcessActive = Get-Process -id !LOCALV_PID! -ErrorAction SilentlyContinue; } if ($timeout -eq 0 -or ^! $ProcessActive) { Stop-Process -Id $args; } } | Out-Null ; $npipeServer = new-object System.IO.Pipes.NamedPipeServerStream('PowerShellCon_!LOCALV_PID!', [System.IO.Pipes.PipeDirection]::In); Try { $npipeServer.WaitForConnection(); $pipeReader = new-object System.IO.StreamReader($npipeServer); while(($msg = $pipeReader.ReadLine()) -notmatch 'QUIT') { $disp='write-host '+$msg+';'; invoke-expression($disp); $npipeServer.Disconnect(); $npipeServer.WaitForConnection(); }; } Finally { $npipeServer.Dispose(); }" 2>NUL
  SET /A LOCALV_TRY=20 >NUL
  :LaunchPowerShellSubProcess_WaitForPipe
  powershell -nop -c "& {sleep -m 50}"
  SET /A LOCALV_TRY=!LOCALV_TRY! - 1 >NUL
  IF NOT "!LOCALV_TRY!" == "0" cmd /C "ECHO -NoNewLine|MORE 1>\\.\pipe\PowerShellCon_!LOCALV_PID!" 2>NUL || GOTO:LaunchPowerShellSubProcess_WaitForPipe
  IF "!LOCALV_TRY!" == "0" EXIT /B 1
  EXIT /B 0

链接到我在同一主题上的原始答案。