[英]How can I use command line arguments to control a batch program that prints multi-colour text?
我有一个批处理脚本,可以在命令提示符的同一行上显示两种或多种颜色的文本。 (以下)
@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"
pause
goto :eof
:ColorText
echo off
<nul set /p ".=%DEL%" > "%~2"
findstr /v /a:%1 /R "^$" "%~2" nul
del "%~2" > nul 2>&1
goto :eof
但是,必须通过使用记事本编辑批处理文件预先在脚本中输入该文本。 我希望能够打开命令提示符并键入以下内容:
cecho /blue hello world!
要么
cecho blue "hello world!"
或者一些简单的东西,我可以提供颜色(最好是字符串而不是颜色代码)和文本(带或不带引号)。
我不知道这对您是否有任何用处,但可以保存脚本的这一部分:
echo off
<nul set /p ".=%DEL%" > "%~2"
findstr /v /a:%1 /R "^$" "%~2" nul
del "%~2" > nul 2>&1
goto :eof
(从“:ColorText”到脚本末尾)并将其另存为“C:\\windows\\system32”中的“ColorText.bat”。 然后在脚本的另一半中,随处可见:
call :ColorText
将其更改为:
call ColorText
(省略冒号)并将该脚本保存为“C:\\windows\\system32”中的colors.bat。 然后打开命令提示符并键入“颜色”。 这就是我希望它运行的方式; 没有额外的命令、安装脚本、文件路径; 只是一个简单的一两个词函数,所有杂乱的代码都在后台运行(看不见)。 然而,上面的想法仍然不会让我从命令提示符指定我自己的文本或颜色......有什么想法吗?
编辑:取 3
创建文件夹C:\\Utilities
。 将此文件夹添加到您的 Path 环境变量,以便 Windows 在那里查找其他脚本和命令。
;C:\\Utilities
,包括分号。 不要删除任何其他文本。 获取: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
现在您可以从任何命令行或脚本中使用此命令。 用法:
CEcho color "text"
编辑:回应您的评论:
您可以通过插入以下行并替换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 "hello world!"
@echo off
call :ColorText %1 "%~2"
...
如果您想使用颜色名称,您必须将它们转换为相应的数字。
cecho blue "hello"
@echo off
if "%1"=="red" set color=0c
if "%1"=="blue" set color=0b
if ...
call :ColorText %color% "%~2"
自Windows XP以来,通过使用 PowerShell 作为通过命名管道链接到控制台输出的子进程,可以快速替代使用 cmd 批处理高效着色。 也可以使用 FindStr 来完成,但 PowerShell 提供了更多选项并且看起来更快。
在保持PowerShell中作为子进程,使用管进行通信的主要兴趣是,显示远远快于发射的PowerShell或FINDSTR为每一行显示。
其他优点:
这是执行此操作的示例代码:
::
:: 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
链接到我关于同一主题的原始答案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.