批处理 - 如何在脚本中读取另一个命令行函数的输出?

时间:2012-07-10 00:30:25

标签: batch-file phpunit

我是批处理脚本的新手,但是,之前我已经完成了一些bash脚本。我的批处理文件将运行另一个程序(即phpunit),该程序将输出一些东西到命令提示符。我将如何让批处理脚本拦截已经输出的东西并根据它做出决定。例如,phpunit通常会打印一个'。'对于每个成功运行的测试,每个测试失败的“F”。如何让批处理脚本捕获此输出并根据它是否看到'。'来执行不同的操作。还是'F'?

3 个答案:

答案 0 :(得分:6)

我首先回答您的实际问题,但这些建议可能对您试图解决的潜在问题有用:

  1. 您可以{a} {{}} {{}} 机器阅读。
  2. PHP是编写命令行脚本的BASH的有效替代方法。我使用BASH来处理简单的东西,但是一旦它超出了几行,或者当我想添加循环,if语句等时,我决定在PHP中正确地完成它。其他人可能会找到perl或python。
  3. 在你的特定情况下,我会用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