根据日志文件输出字符串更改文本颜色的批处理文件

3
我正在尝试使用批处理文件读取日志文件。
  • 如果批处理文件在日志文件中发现“SUCCESS”,则文本应为绿色。
  • 如果批处理文件在日志文件中发现“WARNING”,则文本应为青色。
  • 如果批处理文件在日志文件中发现“ERROR”,则文本应为红色。
当日志文件包含两个或多个不同结果(如“SUCCESS”和“WARNING”)时,它仅适用于其中一个值。在Windows上尝试使用批处理文件读取日志文件。
@echo off
set LogPath=C:\Mworks\logs
set /p MM-DD="Enter Month and Day (MM-DD) to Search logs for success close eg. 08-24: "
set YEAR=2019
@echo searching for %LogPath%\%YEAR%-%MM-DD%*.log
FOR /F "eol=- tokens=1-8 delims= " %%i in ('find /I "LOG ROTATE COMPLETE" %LogPath%\%YEAR%-%MM-DD%*.log') do set result=%%p
echo %result%

(
IF /I %result%==ERROR (goto :ERROR)
)

(
if /I %result%==SUCCESS (goto :SUCCESS)
)

(
if /I %result%==WARNING (goto :WARNING)
)

REM somehow need to catch value at token 8 and color the lines accordingly
REM proper use of enableDelayedExpansion might help but it's quite tough simply with batch script.
REM I've seen hackoo's version of pinger doing it but the code is hard to understand, which part controls what.
:SUCCESS
color 0A
REM this line needs to be on GREEN
FOR /F "eol=- tokens=1-8 delims= " %%i in ('find /I "LOG ROTATE COMPLETE" %LogPath%\2019-%MM-DD%*.log') do @echo %%i %%j %%k %%l %%m %%n %%o %%p
goto end

:ERROR
color 0C
REM this line nees to be on RED
FOR /F "eol=- tokens=1-8 delims= " %%i in ('find /I "LOG ROTATE COMPLETE" %LogPath%\2019-%MM-DD%*.log') do @echo %%i %%j %%k %%l %%m %%n %%o %%p
goto end
:WARNING
REM This line needs to be on CYAN
color 0B
FOR /F "eol=- tokens=1-8 delims= " %%i in ('find /I "LOG ROTATE COMPLETE" %LogPath%\2019-%MM-DD%*.log') do @echo %%i %%j %%k %%l %%m %%n %%o %%p
:end
pause

如果代码找到多个结果,其中结果可能是SUCCESSWARNINGERROR,那么代码将无法正常工作。

    **LOG BEGUN     2019-08-24 03:42:28,662
loading c:Mworksconfiglog4j2.xml
INFO  2019-08-24 03:42:34,100 Initializing configs... :: oracle.retail.mworks.config.mworksProperties [mworks]
INFO  2019-08-24 03:42:34,100 Loading Properties - jar:file:/C:/Mworks/lib/menv-engine.jar!/dtv/res/config/actions.properties :: dtv.util.ResourceUtils [mworks]
INFO  2019-08-24 03:42:34,115 Loading Properties - file:/C:/Mworks/cust_config/version1/actions.properties :: dtv.util.ResourceUtils [mworks]
INFO  2019-08-24 03:42:34,131 Loading Properties - jar:file:/C:/Mworks/lib/menv-engine.jar!/dtv/res/config/environment.properties :: dtv.util.ResourceUtils [mworks]
INFO  2019-08-24 03:42:34,131 Loading Properties - file:/C:/Mworks/cust_config/version1/environment.properties :: dtv.util.ResourceUtils [mworks]
INFO  2019-08-24 03:42:34,146 Loading Properties - jar:file:/C:/Mworks/lib/menv-engine.jar!/dtv/res/config/update.properties :: dtv.util.ResourceUtils [mworks]
INFO  2019-08-24 03:42:34,162 Loading Properties - file:/C:/Mworks/cust_config/version1/update.properties :: dtv.util.ResourceUtils [mworks]
INFO  2019-08-24 03:42:34,162 Loading Properties - jar:file:/C:/Mworks/lib/menv-engine.jar!/dtv/res/config/local.properties :: dtv.util.ResourceUtils [mworks]
INFO  2019-08-24 03:42:34,162 Loading Properties - file:/C:/Mworks/cust_config/version1/local.properties :: dtv.util.ResourceUtils [mworks]
INFO  2019-08-24 03:42:34,584 Loading registration data from c:\Mworks\res\data\registrationdata.json :: oracle.retail.mworks.registration.RegistrationDataManager [mworks]
INFO  2019-08-24 03:42:35,287 Gathering local Client data. :: oracle.retail.mworks.registration.RegistrationDataManager [mworks]
INFO  2019-08-24 03:42:36,334 loading jar:file:/C:/Mworks/lib/menv-engine.jar!/dtv/res/config/MBeanInfoConfig.xml :: dtv.util.config.ConfigHelper [mworks]
INFO  2019-08-24 03:42:36,883 
INFO  2019-08-24 03:42:36,883 Waiting for services to start... :: oracle.retail.mworks.mworks [mworks]
ntly running actions: [startup-lead, create-update-directories, LOG ROTATE] :: oracle.retail.mworks.action.Action [ActionExec-1]
INFO  2019-08-24 03:42:40,447 Action [CreateUpdateDirectories :: oracle.retail.mworks.atoms.CreateUpdateDirectories] complete. State: SUCCESS, Result: -----------------------------------
The text below should be in RED
----------------------------------
INFO  2019-08-24 03:42:40:03,060 LOG ROTATE complete.  Status: ERROR  Created update directories. :: oracle.retail.mworks.atoms.Atom [ActionExec-1]


INFO  2019-08-24 03:42:40,447 Currently running actions: [startup-lead, LOG ROTATE] :: oracle.retail.mworks.action.Action [ActionExec-1]
INFO  2019-08-24 03:42:40,447 Action [create-update-directories] returned state [SUCCESS] with message [Created update directories.] :: 

The text below should be in cyan
---------------------------------------
INFO  2019-08-24 04:44:03,060 LOG ROTATE complete.  Status: WARNING 

LOT OF lines  DELETED

The text below should be in green
----------------------------------------
INFO  2019-08-24 05:44:03,060 LOG ROTATE complete.  Status: SUCCESS :: oracle.retail.xenvironment.action.Action [ActionExec-2]
sample log

这是我的单色输出

类似于这样:

@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"
)
call :chooseColor 0A "This is colored Green means SUCCESS"
echo.
call :chooseColor 0B "This is colored Cyan means WARNING"
echo.
call :chooseColor 0C "This is colored Red means ERROR"
echo.
pause
goto eof
:chooseColor
echo off
<nul set /p ".=%DEL%" > "%~2"
findstr /v /a:%1 /R "^$" "%~2" nul
del "%~2" > nul 2>&1i
:eof

输出应该像这样


编辑您的问题并包含一些日志文件内容示例。您只需要一个FOR /F循环,而且这样做会更好:Find /I "Log roatate complete" ^<"%LogPath%\log.2019-%MM-DD%*.log"。但在尝试使用用户输入之前,您应该实现某种验证。 - Compo
我无法粘贴日志? - kallu
这是日志 https://ufile.io/xw805ie3 - kallu
1
使用编辑按钮并将其添加到您的问题中,_(使用{}按钮格式化为代码)_。评论区不是您的问题的一部分,因为StackOverflow无法控制第三方网站,因此不建议添加外部链接。 - Compo
4个回答

2

使用 ANSI Escape 代码的纯批处理解决方案需要更高版本的 Win10。
困难在于 ESC 符号十六进制为 0x1b,十进制为 27,不是所有编辑器都能轻松提供。

这里使用 certutil 将十六进制转换为二进制来解决。

编辑将 for 循环嵌套到小写的 %%f 的 for /f 中

Translated:
:: Q:\Test\2019\08\31\SO_57736435.cmd
@echo off
:restart
set "MM-DD="
set /p MM-DD="Enter Month and Day (MM-DD) to Search logs for success close eg. 08-24: "
if not defined MM-DD Exit /B 0

set "LogPath=C:\Mworks\logs"
set "File=%LogPath%\log.2019-%MM-DD%*.log"
if not exist "%File%" (Echo %File% doesn't exist&pause&goto :restart)

:: ANSI Escape codes, supported with Win10 again
Call :GetCSI

FOR %%f in ("%File%") Do FOR /F "usebackq tokens=1-8* delims= " %%A in ("%%f"
) do if /I "%%A%%D%%E%%F%%G"=="INFOLogRotateComplete.Status:" (
  Call :%%H "%%A %%B %%C %%D %%E %%F %%G %%H %%I"
) Else (
  Echo:%%A %%B %%C %%D %%E %%F %%G %%H %%I
)
Pause
exit /B 0

:Warning
Echo(%CSI%36m%~1%CSI%0m
Goto :Eof

:Success
Echo(%CSI%32m%~1%CSI%0m
Goto :Eof

:Error
Echo(%CSI%31m%~1%CSI%0m
Goto :Eof

:GetCSI
echo 1B 5B>CSI.hex
Del CSI.bin >NUL 2>&1
certutil -decodehex CSI.hex CSI.bin >NUL 2>&1
Set /P CSI=<CSI.bin
Goto :Eof

enter image description here


那很整洁。 我无法投票。 感谢您的反馈!拥有不到15个声望值的用户投票会被记录,但不会改变公开显示的帖子得分。 - kallu
刚刚发现代码无法处理 * 或 (),只会显示文件不存在。 日志格式将是 粗体log.Year.DD-MM(1).log 或 (2).log 粗体 等等。因此,当我指定字符串 [log.Year.DD-MM^*.log] 或 [log.Year.DD-MM^(*^1)] 时,它只会显示文件不存在。 - kallu
努力修复代码,但我想它超出了我的能力。set "LogPath=C:\Mworks\logs\" set "File=log.2019-%MM-DD%*.log" set combo=%Logpath%%File% FOR /F "usebackq tokens=1-8 delims= " %%A in ("%combo%" ) do if /I "%%A%%D%%E%%F%%G"=="INFOLogRotateComplete.Status:" ( Call :%%H "%%A %%B %%C %%D %%E %%F %%G %%H %%I" ) Else ( Echo:%%A %%B %%C %%D %%E %%F %%G %%H %%I )如果只指定单个文件名,则可以正常工作,但对于通配符 *.log,它会说“系统找不到带有”**“的文件”,如何使用 cmd 将多个文件传递为变量? - kallu
由于缺少换行符,将完整的批处理贴在评论中没有意义。我会将“for”添加到上面的批处理中。 - user6811411
新贡献者提示:如果一个答案解决了你的问题,或者你发现它很有帮助,你应该考虑接受这个答案和/或投票支持(一旦你获得了15分的声誉,它将被看到)。 - user6811411
显示剩余2条评论

1

批处理脚本语言绝对不适合这个任务,你需要:

  • 完整的正则表达式支持
  • 能够轻松标记单行的能力

顺便说一下,你的批处理有很多错误和短处。

这个PowerShell脚本(使用单个固定文件名)应该可以满足你的需求:

## create a hash table with the color mappings
$FG = @{SUCCESS='green';WARNING='cyan';ERROR='red'}

# Regular Expression with a capture group to grep 
# the Status, see https://regex101.com/r/d0swXC/1
$RE = '^INFO  (.*?) LOG ROTATE complete\. +Status: (?<Status>[^ ]+).*'

ForEach($Line in Get-Content .\file.log){
    if ($Line -match $RE){
        Write-Host -ForegroundColor $FG[$Matches.Status] $Line
    } Else {
        Write-Host $Line
    }
}

enter image description here


这是一个很好的 PowerShell 示例,.ps1 文件的运行已被禁用。我已经更正了批处理脚本。一个名为 log.2019-08-24(1).log 的日志文件应该存在于 C:\Mworks\logs 文件夹中。 - kallu
使用 ANSI 转义码的纯批处理解决方案需要更高版本的 Win10。困难在于 ESC 符号十六进制 0x1b,十进制 27,并非所有编辑器都能轻松提供。前景色红色=ESC[31m,绿色=ESC[32m,青色=ESC[36m,重置颜色=ESC[0m - user6811411
我同意@LotPings,只使用纯批处理脚本在DOS命令的有限功能下确实非常困难。 - kallu

1
自Windows XP以来,使用PowerShell作为子进程通过命名管道链接到控制台输出,是一种快速且有效的颜色替代方案。也可以使用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

0

对于Windows 10,在本地批处理中将%~dp0input.txt替换为日志路径:

::: Author T3RRY : Created 09/04/2021 : Version 1.0.1
:::
::: 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
 )
(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"

:# Virtual Terminal 'VT' sequence Resource : 
:# https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences

::# usage: %$Cout% /Switch /Switch value
::# -----------------------------------------------------------------------------------------------------
::# Available Switches     : Description:
::# -----------------------------------------------------------------------------------------------------
::# /Help                  : This help screen
::#
::# /S String              : String to be output
::# /S String{FS}          : '/' must be substituted with {FS}
::#
::# /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
::#
::# /Y Integer             : Move cursor to Line Integer   [ absolute ]
::# /X Integer             : Move cursor to Column Integer [ absolute ]
::# /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
::# /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
::# /Z 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.
::# -----------------------------------------------------------------------------------------------------
::#

:# Note on macro switch handling: Switches must not share a common prefix.
:#  - IE:
:#   - Invalid: D and DE [ switch assessment method would assign D as true if /DE used ]
:#   - Valid  : DA and DE
 Set Switches= "help" "S" "C" "Y" "X" "U" "D" "R" "L" "H" "Alt" "Main" "K" "Z" "I" "N"

 Set $Cout=For %%n in (1 2)Do if %%n==2 (%\n%
  For %%G in ( %Switches% )Do set "Switch[%%~G]="%\n%
  Set "leading.args=!args:*/=!"%\n%
  For /F "Delims=" %%G in ("!leading.args!")Do Set "leading.args=!args:/%%G=!"%\n%
  Set ^"args=!args:"=!" %\n%
  Set "i.arg=0"%\n%
  For %%G in (!leading.args!)Do (%\n%
   Set /A "i.arg+=1"%\n%
   Set "arg[!i.arg!]=%%~G"%\n%
  )%\n%
  For %%G in ( %Switches% )Do If not "!args:/%%~G=!" == "!args!" (%\n%
   If not "!args:/%%~G: =!" == "!args!" Set "args=!args:/%%~G: =/%%~G !"%\n%
   If not "!args:/%%~G =!" == "!args!" Set "switch[%%~G]=!Args:*/%%~G =!"%\n%
   If not "!args:/%%~G:=!" == "!args!" Set "switch[%%~G]=!Args:*/%%~G:=!"%\n%
   If not "!switch[%%~G]:*/=!" == "!switch[%%~G]!" (%\n%
    Set "Trail[%%~G]=!switch[%%~G]:*/=!"%\n%
    For %%v in ("!Trail[%%~G]!")Do (%\n%
     Set "switch[%%~G]=!switch[%%~G]: /%%~v=!"%\n%
     Set "switch[%%~G]=!switch[%%~G]:/%%~v=!"%\n%
    )%\n%
    Set "Trail[%%~G]="%\n%
    If "!switch[%%~G]:~-1!" == " " Set "switch[%%~G]=!switch[%%~G]:~0,-1!"%\n%
    If "!switch[%%~G]!" == "" Set "switch[%%~G]=true"%\n%
   )%\n%
  )%\n%
  If "!Switch[help]!" == "true" (For /F "Tokens=1,2 Delims=#" %%Y in ('findstr /BLIC:"::#" "%~f0"')Do Echo(%%Z) ^& Timeout /T 1 /Nobreak ^> nul ^& Pause%\n%
  If not "!Switch[C]!" == ""    (Set "_Color_=%\E%[!Switch[C]:,=m%\E%[!m")Else Set "_Color_="%\n%
  If not "!Switch[Y]!" == ""    (Set "_Ypos_=%\E%[!Switch[Y]!d")Else Set "_Ypos_="%\n%
  If not "!Switch[X]!" == ""    (Set "_Xpos_=%\E%[!Switch[X]!G")Else Set "_Xpos_="%\n%
  If not "!Switch[U]!" == ""    (Set "_Yoffset_=%\E%[!Switch[U]!A")Else Set "_Yoffset_="%\n%
  If not "!Switch[D]!" == ""    Set "_Yoffset_=%\E%[!Switch[D]!B"%\n%
  If not "!Switch[R]!" == ""    (Set "_Xoffset_=%\E%[!Switch[R]!C")Else Set "_Xoffset_="%\n%
  If not "!Switch[L]!" == ""    Set "_Xoffset_=%\E%[!Switch[L]!D"%\n%
  If "!Switch[H]!" == "-"       Set "_Cursor_=%\E%[?25l"%\n%
  If "!Switch[H]!" == "+"       Set "_Cursor_=%\E%[?25h"%\n%
  If "!Switch[Main]!" == "true" (Set "_Buffer_=%\E%[?1049l")Else Set "_Buffer_="%\n%
  If "!Switch[Alt]!" == "true"  Set "_Buffer_=%\E%[?1049h"%\n%
  If not "!Switch[K]!" == ""    (Set "_LineClear_=%\E%[K")Else Set "_LineClear_="%\n%
  If not "!Switch[Z]!" == ""    (Set "_Delete_=%\E%[!Switch[Z]!P")Else Set "_Delete_="%\n%
  If not "!Switch[I]!" == ""    (Set "_Insert_=%\E%[!Switch[I]!@")Else Set "_Insert_="%\n%
  If not "!Switch[S]!" == ""    (Set "_String_=!Switch[S]:{FS}=/!")Else Set "_String_="%\n%
  ^< nul set /P "=!_Buffer_!!_Cursor_!!_Ypos_!!_YOffset_!!_Xpos_!!_XOffset_!!_Delete_!!_Insert_!!_Color_!!_LineClear_!!_String_!%\E%[0m"%\n%
  If "!Switch[N]!" == "true"    Echo(%\n%
 ) Else Set args=

:# enable macro using Setlocal EnableExtensions EnableDelayedExpansion

 CLS
 If "%~1." == "/?." (
  Setlocal EnableExtensions EnableDelayedExpansion
  %$Cout% /help
  Goto :EOF
 )

 For /F "usebackq Delims=" %%G in ("%~dp0input.txt")Do (
  Set "Line=%%G"
  Setlocal EnableExtensions EnableDelayedExpansion
  If not "!Line:SUCCESS=!" == "!Line!" (
   %$cout% /C 32 /N /S "!line:/={FS}!"
  ) Else If not "!Line:WARNING=!" == "!Line!" (
   %$cout% /C 36 /N /S "!line:/={FS}!"
  ) Else If not "!Line:ERROR=!" == "!Line!" (
   %$cout% /C 31 /N /S "!line:/={FS}!"
  ) Else (
   %$cout% /N /S "!line:/={FS}!"
  )
  Endlocal
 )
 
Goto :eof


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接