【问题标题】:Batch - How do I read the output of another command line function in a script?批处理 - 如何读取脚本中另一个命令行函数的输出?
【发布时间】:2012-07-10 00:30:25
【问题描述】:

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

【问题讨论】:

    标签: batch-file phpunit


    【解决方案1】:

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

    1. 您可以have phpunit log results 以一种更方便的方式 机器阅读。
    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 作业来运行您的所有测试并确保没有任何问题。所以我就去use a regex寻找“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)
    ...
    

    【讨论】:

      【解决方案2】:

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

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

      希望这会有所帮助。

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

      【讨论】:

      • 正如我在示例中展示的那样,使用反斜杠与您在那里所做的有区别吗?我认为获得输出是微不足道的部分,而上述代码 sn-p 中的“做某事”才是真正的挑战!
      • 是的,“做某事”部分绝对是更难的部分,这导致我在 PHP 中使用类似“exec('phpunit sometest', $output)”而不是 bash。跨度>
      【解决方案3】:

      关于您的解决方案的一个注意事项:如果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 之后的命令。如果要添加更多命令,请将正文括在括号中。如果你把它们放在同一行,你可以用&amp; 分隔命令,或者你可以将正文分成多行,如下所示:

      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 && (
      ...
      

      【讨论】:

        猜你喜欢
        • 2016-04-10
        • 2018-11-07
        • 2011-11-17
        • 2015-11-01
        • 1970-01-01
        • 2014-12-03
        • 1970-01-01
        • 2015-09-28
        • 1970-01-01
        相关资源
        最近更新 更多