我对批处理脚本还不是很熟悉,但之前做过一些Bash脚本。我的批处理文件将运行另一个程序(即phpunit),这个程序将向命令提示符输出一些内容。我该如何在批处理脚本中截取这些输出并根据其做出决策?例如,phpunit通常会为每个成功运行的测试打印“.”,而为每个失败的测试打印“F”。我该如何让批处理脚本捕获这些输出并根据它是否看到“.”或“F”来执行不同的操作?
我对批处理脚本还不是很熟悉,但之前做过一些Bash脚本。我的批处理文件将运行另一个程序(即phpunit),这个程序将向命令提示符输出一些内容。我该如何在批处理脚本中截取这些输出并根据其做出决策?例如,phpunit通常会为每个成功运行的测试打印“.”,而为每个失败的测试打印“F”。我该如何让批处理脚本捕获这些输出并根据它是否看到“.”或“F”来执行不同的操作?
在你的特定情况下,我会使用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作业。因此,我将使用正则表达式来搜索“FAILURES”一词:(请参考)
#!/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)
...
如果有其他人正在寻找相同的解决方案,可以通过以下方式实现:
setlocal
someprog.exe > temp.txt
set /p PROGOUTPUT= < temp.txt
del temp.txt
REM do something with %PROGOUTPUT% here
endlocal
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
是循环变量,循环体在本例中只包含一个命令,即跟随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
:
someprog.exe > NUL && (
...