Function 如何使用命令行参数控制打印多色文本的批处理程序?

Function 如何使用命令行参数控制打印多色文本的批处理程序?,function,colors,batch-file,command,Function,Colors,Batch File,Command,我有一个批处理脚本,可以在命令提示符的同一行上显示两种或更多颜色的文本。(下文) 或 或者一些简单的东西,我可以提供颜色(最好是字符串而不是颜色代码)和文本(带或不带引号) 我不知道这对您是否有用,但可以保存脚本的这一部分: echo off <nul set /p ".=%DEL%" > "%~2" findstr /v /a:%1 /R "^$" "%~2" nul del "%~2" > nul 2>&1 goto :eof 将其更改为: call Co

我有一个批处理脚本,可以在命令提示符的同一行上显示两种或更多颜色的文本。(下文)

或者一些简单的东西,我可以提供颜色(最好是字符串而不是颜色代码)和文本(带或不带引号)


我不知道这对您是否有用,但可以保存脚本的这一部分:

echo off
<nul set /p ".=%DEL%" > "%~2"
findstr /v /a:%1 /R "^$" "%~2" nul
del "%~2" > nul 2>&1
goto :eof
将其更改为:

call ColorText
(省略冒号)
并将该脚本另存为“C:\windows\system32”中的colors.bat。然后打开命令提示符并键入“colors”。这就是我希望它发挥作用的方式;没有其他命令、设置脚本、文件路径;仅仅是一个简单的一两个单词的函数,所有这些乱七八糟的代码都在后台进行(看不见)。但是,上述想法仍然不允许我从命令提示符指定自己的文本或颜色。。。。有什么想法吗?

编辑:拿3个

创建文件夹
C:\Utilities
。将此文件夹添加到Path环境变量中,以便Windows在其中查找其他脚本和命令

  • 打开控制面板、系统、高级系统设置(或Windows XP中的“高级”)、环境变量
  • 在“系统变量”列表中,选择“路径”变量。
    不要把接下来的步骤搞砸了
  • 按编辑
  • 将光标放在行尾,确保未选择任何文本
  • 添加文本
    ;C:\Utilities
    ,包括分号。不要删除任何其他文本
  • 按OK。
    再次放松呼吸。
  • 根据需要多次按OK以关闭所有窗口
  • 获取
    :ColorText
    标签后面的脚本,并将其保存到
    C:\Utilities\cecho.bat
    。将
    @
    放在
    echo off
    前面,以防止脚本执行期间出现
    echo off

    CEcho.bat

    @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"
    )
    <Nul Set /p ".=%DEL%" > "%~2"
    FindStr /v /a:%1 /R "^$" "%~2" Nul
    Del "%~2" > Nul 2>&1
    EndLocal
    
    编辑:回应您的评论:

    通过插入以下行并替换
    FindStr
    行,可以使用颜色词:

    Set Color=%1
    If %1==blue Set Color=9
    If %1==red Set Color=C
    etc...
    FindStr /v /a:%Color% /R "^$" "%~2" Nul
    
    现在您可以键入:

    CEcho red "apple"
    CEcho blue "water"
    CEcho A "grass"
    CEcho 6 "dirt"
    CEcho 26 "tree"
    

    请注意,颜色词区分大小写。

    您可以使用批处理参数%1、%2、%n作为颜色和内容的参数

    cecho 0a“你好,世界!”

    如果要使用颜色名称,必须将它们转换为相应的数字

    cecho blue“你好”

    自Windows XP以来,通过使用PowerShell作为通过命名管道链接到控制台输出的子进程,使用cmd batch高效地替代color。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
    
    此“代码”是在
    上使用延迟扩展编写的,但可以重写以在没有延迟扩展的情况下工作。有很多安全点要考虑,不要直接在野外使用。 如何使用它:

    @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
    
    @ECHO关闭
    setLocalEnableExtensions
    如果错误级别为1(
    回声扩展不适用
    退出/B 1
    )
    ::
    SETLOCAL ENABLEDELAYEDEXPANSION
    如果错误级别为1(
    回声膨胀不适用
    退出/B 1
    )
    调用:启动PowerShellSubProcess
    如果不是错误级别0退出/B 1
    呼叫:青色“我用青色写这个”
    呼叫:蓝色“我用蓝色写这个”
    呼叫:绿色“这是绿色的”
    呼叫:红色-非WLINE“和混合红色”
    呼叫:黄色“带黄色”
    CALL:Green“并且不需要为()&|;、%“^等问题而烦恼…”
    退出/b0
    :颜色
    ECHO-foregroundcolor%*>\\.\pipe\PowerShellCon\!LOCALV_-PID!
    回声[|设置/P=>NUL
    后藤:EOF
    :蓝色
    ECHO-foregroundcolor Blue%*>\\.\pipe\PowerShellCon\\!LOCALV\\ PID!
    回声[|设置/P=>NUL
    后藤:EOF
    :绿色
    ECHO-foregroundcolor绿色%*>\\.\pipe\PowerShellCon\\!LOCALV\\ PID!
    回声[|设置/P=>NUL
    后藤:EOF
    :红色
    ECHO-foregroundcolor红色%*>\\.\pipe\PowerShellCon\\!LOCALV\\ PID!
    回声[|设置/P=>NUL
    后藤:EOF
    :黄色
    ECHO-foregroundcolor Yellow%*>\\.\pipe\PowerShellCon\\!LOCALV\\ PID!
    回声[|设置/P=>NUL
    后藤:EOF
    ::
    ::在后台启动链接到控制台的PowerShell子进程,然后
    ::正在通过命名管道PowerShellCon_u%PID%进行搜索
    ::
    ::参数:
    ::[PID]:控制台进程ID用作命名管道的标识符,默认情况下为启动器PID。
    :[超时]:子进程的最大生存时间(秒),默认为300。如果为-1,则子进程
    ::进程%PID%仍处于活动状态时,将不会终止。
    ::返回:
    ::0如果子PowerShell已成功启动且命名管道可用。
    ::1如果失败。
    ::2如果我们不能得到PID。
    ::3如果PowerShell不存在或不工作。
    ::
    :LaunchPowerShellSubProcess
    设置本地v_PID=
    设置LOCALV_TIMEOUT=300
    如果不是“%~1”==”,则设置LOCALV_PID=%~1
    如果不是“%~2”==”,则设置本地V_超时=%~2
    powershell-命令“$\u2>&1>NUL
    如果不是“!ERRORLEVEL!”==“0”退出/B 3
    如果“!LOCALV_PID!”==”(
    对于('powershell-命令“$parentId=(Get-WmiObject Win32_进程-Filter ProcessId=$PID)。ParentProcessId;写入主机(Get-WmiObject Win32_进程-Filter ProcessId=$parentId)。ParentProcessId;”)执行以下操作(
    设置LOCALV_PID=%%P
    )
    )
    如果“!LOCALV_PID!”==“退出/B 2
    启动/B powershell-命令“$cmdPID=$PID;启动作业-ArgumentList$cmdPID-ScriptBlock{$ProcessActive=$true;$timeout=!LOCALV_timeout!;而(!LOCALV_timeout!-eq-1-或$timeout-gt 0)-和$ProcessActive){启动睡眠-s1;$timeout-=1;$ProcessActive=Get-
    
    CEcho color "text"
    
    Set Color=%1
    If %1==blue Set Color=9
    If %1==red Set Color=C
    etc...
    FindStr /v /a:%Color% /R "^$" "%~2" Nul
    
    CEcho red "apple"
    CEcho blue "water"
    CEcho A "grass"
    CEcho 6 "dirt"
    CEcho 26 "tree"
    
    @echo off
    call :ColorText %1 "%~2"
    ...
    
    @echo off
    if "%1"=="red" set color=0c
    if "%1"=="blue" set color=0b
    if ...
    call :ColorText %color% "%~2"
    
    ::
    :: 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
    
    @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