我正在尝试将从程序输出的行传输到另一个脚本,该脚本将实时读取行并根据行中的内容执行某些操作。
例如,输出是
$program.exe
Program Started
Processing info
Work Set Started
Work Set Ended
Results are..
Ending Program
我希望将上传程序输出“工作集开始”的脚本发送到可以触发另一个程序的脚本
我在trigger.bat
中尝试过以下操作@echo off
SETLOCAL
FOR /F "tokens=1* delims=]" %%A IN ('FIND /N /V ""') DO (
IF "%%B" == "Work Set Started" (
ProgramB.exe
)
)
ENDLOCAL
当我运行以下
时$program.exe | trigger.bat
ProgramB.exe未实时启动,但来自trigger.bat的for循环在收集管道的所有输出后执行。
我做错了吗?我必须使用PowerShell吗?
答案 0 :(得分:2)
FOR /F
命令首先收集执行命令的所有输出,并开始处理每个输出行,直到命令结束。
您可以通过以下方式修改trigger.bat
文件代码:
@echo off
SETLOCAL
:nextLine
set /P "line="
echo Line received: "%line%"
FOR /F "tokens=1* delims=]" %%A IN ("%line%") DO (
IF "%%B" == "Work Set Started" ECHO ProgramB.exe
IF "%%B" neq "Ending Program" GOTO NextLine
)
但是,如果$program.exe
的输出生成得太快,可能会出现一些同步问题。我使用这个output.txt
文件测试了这段代码:
[1]$program.exe
[2]Program Started
[3]Processing info
[4]Work Set Started
[5]Work Set Ended
[6]Results are..
[7]Ending Program
如果我这样做:type output.txt | trigger.bat
程序失败,但如果通过此output.bat
程序缓慢生成输出行:
@echo off
setlocal EnableDelayedExpansion
for /F "delims=" %%a in (output.txt) do (
set /A "rand=!random! %% 4 + 2"
ping -n !rand! localhost > NUL
echo %%a
)
...然后方法正常工作:
C:\> output.bat | trigger.bat
Line received: "[1]$program.exe "
Line received: "[2]Program Started"
Line received: "[3]Processing info"
Line received: "[4]Work Set Started"
ProgramB.exe
Line received: "[5]Work Set Ended"
Line received: "[6]Results are.."
Line received: "[7]Ending Program"
所以你需要根据你的具体情况测试这个方法......
答案 1 :(得分:1)
使用简单代码测试以生成输出
@echo off
setlocal enableextensions disabledelayedexpansion
>"programOutput.txt" (
echo(Program Started
echo(Processing info
echo(Work Set Started
echo(Work Set Ended
echo(Results are..
echo(Ending Program
)
set program=findstr "^" programOutput.txt
%program% | trigger.cmd
trigger.cmd
代码可能类似于
@echo off
setlocal enableextensions disabledelayedexpansion
if "%~1"==".monitor." ( call :monitor ) else ( call :start )
goto :eof
:start
echo .... Entering monitor
for %%t in ("%temp%\%~n0.%random%%random%%random%%random%%random%.tmp") do (
type nul >"%%~ft"
findstr "^" > "%%~ft" | ( <"%%~ft" "%~f0" .monitor. & echo Start program B here )
) & 2>nul del /q "%%~ft"
echo .... Main program ended - Leaving monitor
goto :eof
:monitor
rem Try to read data. In case of failure wait and repeat
set /p "data=" || (
>nul ping -n 2 ""
goto :monitor
)
echo(.... monitor has retrieved [%data%]
if /i "%data%"=="Work Set Started" (
echo(.... !!! : detected work set start. Leaving monitor
goto :eof
)
rem No end of monitoring condition found. Try again
goto :monitor
正如Aacini所说,
for /f
的问题是在开始处理之前必须检索所有数据。 set /p
的循环问题是管道两侧的同步。但这个问题有一个解决方法。您可以使用中间文件。也就是说,您可以将命令的输出重定向到文件,并且在程序正在写入的同时,您可以从文件中读取。不是防弹但更稳定。
更安全的处理方式是使用某种方式指示每条线的起始位置。这是另一个trigger.cmd
替代方法,它使用find /n
命令处理监视循环中正在处理的程序的输出。如果输入缓冲区中的第一个字符是[
,我们将假设我们找到了一行的开头,否则,它是一个续行。
@echo off
setlocal enableextensions disabledelayedexpansion
if "%~1"==".monitor." ( call :monitor ) else ( call :start )
goto :eof
:start
echo .... Entering monitor
set "buffer="
for %%t in ("%temp%\%~n0.%random%%random%%random%%random%%random%.tmp") do (
type nul >"%%~ft"
find /n /v "" > "%%~ft" | ( <"%%~ft" "%~f0" .monitor. & echo Start program B here )
) & 2>nul del /q "%%~ft"
echo .... Main program ended - Leaving monitor
goto :eof
:monitor
rem Try to read data. In case of failure wait and repeat
set /p "data=" || (
>nul ping -n 2 ""
goto :monitor
)
echo(.... monitor has retrieved [%data%]
rem The output of the process is being numerated by find /n
rem so each line is in the form [9]xxxxxxx
if not "%data:~0,1%"=="[" (
rem If we don not have a line start, append to previous buffer
set "buffer=%buffer%%data%"
) else (
rem New line found to process
set "buffer=%data%"
)
rem Remove initial [number] data
for /f "tokens=2 delims=]" %%a in ("%buffer%") do (
echo(.... checking program output [%%a]
if /i "%%a"=="Work Set Started" (
echo(.... !!! detected work set start. Leaving monitor
goto :eof
)
)
rem No end of monitoring condition found. Try again
goto :monitor
注意:虽然在编写上一段代码时并不知道,但我已经复制了dbenham的工作(而不是最好的方式)。请参阅this post,了解相同想法的改进版本。