3

我对批处理脚本相当陌生,但是,我以前做过一些 bash 脚本。我的批处理文件将运行另一个程序(即 phpunit),该程序将向命令提示符输出一些内容。我将如何让批处理脚本拦截这些已输出的内容并根据它做出决策。例如,phpunit 通常会打印一个 '.' 成功运行的每个测试和失败的每个测试的“F”。我如何让批处理脚本捕捉这个输出并根据它是否看到'。'做一些不同的事情 还是“F”?

4

3 回答 3

6

我将首先不回答您的实际问题,但这些建议可能对您要解决的任何潜在问题有用:

  1. 您可以以一种更易于机器阅读的方式获取 phpunit 日志结果
  2. PHP 是用于编写命令行脚本的 BASH 的有效替代方案。我将 BASH 用于简单的东西,但是一旦它超出了几行,或者当我想添加循环、if 语句等时,我决定在 PHP 中正确地完成它。其他人可能会使用 perl 或 python。

在你的特殊情况下,我会用 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 工作来运行你的所有测试并确保没有任何问题。所以我将使用正则表达式来寻找“失败”这个词:

#!/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)
...
于 2012-07-11T00:00:45.470 回答
1

如果其他人碰巧正在寻找相同的解决方案,可以通过以下方式实现:

setlocal
someprog.exe > temp.txt
set /p PROGOUTPUT= < temp.txt
del temp.txt
REM do something with %PROGOUTPUT% here
endlocal

希望这会有所帮助。

编辑:我还想注意,虽然您可以使用上面的方法,但我最终还是使用 PHP 来执行此操作,类似于下面 Darren Cook 的建议。

于 2012-07-10T16:15:43.300 回答
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情况下,循环体只包含一个命令,即后面的命令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 && (
...
于 2012-07-10T22:52:06.830 回答