我是批处理脚本的新手,但是,之前我已经完成了一些bash脚本。我的批处理文件将运行另一个程序(即phpunit),该程序将输出一些东西到命令提示符。我将如何让批处理脚本拦截已经输出的东西并根据它做出决定。例如,phpunit通常会打印一个'。'对于每个成功运行的测试,每个测试失败的“F”。如何让批处理脚本捕获此输出并根据它是否看到'。'来执行不同的操作。还是'F'?
答案 0 :(得分:6)
我首先回答您的实际问题,但这些建议可能对您试图解决的潜在问题有用:
在你的特定情况下,我会用PHP而不是BASH来做,因为它可能最终需要一些复杂的解析。但是让我们看看如何在BASH中做一些简单的事情。挑战是输出可能如下所示:
PHPUnit 3.4.5 by Sebastian Bergmann.
......................................
Time: 10 seconds, Memory: 9.00Mb
OK (38 tests, 660 assertions)
或者看起来像这样:
PHPUnit 3.4.5 by Sebastian Bergmann.
............................................................ 60 / 380
............................................................ 120 / 380
...............................................S............ 180 / 380
.......S.................................................... 240 / 380
............................................................ 300 / 380
............................................................ 360 / 380
....................
Time: 01:44, Memory: 14.50Mb
OK, but incomplete or skipped tests!
Tests: 380, Assertions: 6546, Skipped: 2.
或者看起来像这样:
PHPUnit 3.4.5 by Sebastian Bergmann.
..IF
Time: 0 seconds, Memory: 8.00Mb
There was 1 failure:
1) MyTest::testTemp
Failed asserting that <boolean:false> is true.
/path/to/myTest.php:68
FAILURES!
Tests: 4, Assertions: 5, Failures: 1, Incomplete: 1.
我猜你的应用程序就像是一个小时的cron工作,可以运行你所有的测试并确保没有任何破坏。所以我只是去have phpunit log results寻找“失败”这个词:
#!/bin/bash
RESULT=`phpunit tests/myTest.php`
if [[ $RESULT =~ FAILURES ]]
then
echo "Excuse me, Sir, but we have a problem in the unit tests...";echo "$RESULT"
fi
我正在使用反引号来捕获输出。一些BASH专家会告诉您使用$()
代替。无论哪种方式都在这里工作:
....
RESULT=$(phpunit tests/myTest.php)
...
答案 1 :(得分:1)
如果其他人碰巧正在寻找相同的解决方案,可以通过以下方式实现:
setlocal
someprog.exe > temp.txt
set /p PROGOUTPUT= < temp.txt
del temp.txt
REM do something with %PROGOUTPUT% here
endlocal
希望这有帮助。
编辑: 我还要注意,虽然你可以使用上面的方法,但我最终使用PHP来完成类似于Darren Cook在下面提出的建议。
答案 2 :(得分:0)
关于您的解决方案的一个注意事项:如果someprog.exe
生成空输出(无结果或只是空行),SET/ P
语句将不会更改PROGOUTPUT
的值,这意味着变量将保留其先前的值,如果有的话。因此,如果每次执行脚本可以多次运行该段代码,则可能需要确保获取的输出与最近的someprog
调用相关,而不是与之前的调用相关。
除此之外,您的代码还可以,但在FOR /F
循环的帮助下,您可以不使用临时文件:
SETLOCAL
SET PROGOUTPUT=
FOR /F "delims=" %%L IN ('someprog.exe') DO SET "PROGOUTPUT=%%L"
REM do something with %PROGOUTPUT% here
ENDLOCAL
请注意,这假设程序只生成一行输出。
"delims="
参数告诉循环命令忽略任何分隔符并将整行视为单个值。 %%L
是循环变量,循环体只包含一个命令,在{0}}之后。如果要添加更多命令,请将正文括在括号中。如果将命令放在同一行,您可以将命令与DO
分开,或者可以将主体分成多行,如下所示:
&
如果可以教你的程序返回退出代码,那么还有一种完全不同的方法。如果可以,请使用FOR /F "delims=" %%L IN ('someprog.exe') DO (
SET "PROGOUTPUT=%%L"
do something else
)
表示成功返回,使用非零代码表示任何类型的故障。在这种情况下,您的批处理脚本可能如下所示:
0
您可能仍希望生成输出作为结果的可视指示(在与批处理脚本分开运行程序时可能很有用)。要在批处理脚本中运行时隐藏输出,只需将其重定向到someprog.exe && (
do something in case of "success" (one or more commands)
) || (
do something in case of "failure" (one or more commands)
)
:
NUL