代码之家  ›  专栏  ›  技术社区  ›  David Ferenczy Rogožan Hugo L.M

命令输出在Powershell中打印而不是捕获

  •  1
  • David Ferenczy Rogožan Hugo L.M  · 技术社区  · 7 年前

    > $output = python3 --version
    > Write-Host $output
    Python 3.7.0
    

    python3打印它的版本,但是它被捕获到变量中 $output 控制台上什么也不显示。如预期:

    >>写入主机$output
    

    但是在python2中,它不起作用。python2打印它的版本,但是在控制台上显示它的版本,而不是捕获和变量 $输出 是空的。

    > $output = python2 --version
    Python 2.7.15
    > Write-Host $output
    
    >
    

    > $output = (python2 --version)  # use a subcommand
    Python 2.7.15
    > $output = "$(python2 --version)"  # enclose the subcommand into a string
    Python 2.7.15
    

    如果我把它用在 Write-Command ,输出如下所示:

    > Write-Host "Python version: $(python2 --version)"
    Python 2.7.15
    Python version:
    >
    

    1 回复  |  直到 7 年前
        1
  •  3
  •   David Ferenczy Rogožan Hugo L.M    7 年前

    是因为 将版本打印到 stderr 而不是 stdout . 分配程序调用的输出捕获 标准 标准错误 默认情况下打印到控制台,这就是 $output 变量为空,版本将打印到控制台。详见下文。

    tl;dr:

    # Redirect stderr to the success output stream and convert to a string.
    $output = (python --version 2>&1).ToString()
    # $? is now $True if python could be invoked, and $False otherwise
    

    倍数 标准线 ,使用:

    • .ForEach() :

      $output = (python --version 2>&1).ForEach('ToString')
      
    • PSv3-,使用 ForEach-Object cmdlet (其内置别名为 % ):

      # Note: The (...) around the python call are required for
      #       $? to have the expected value.
      $output = (python --version 2>&1) | % { $_.ToString() }
      
      # Shorter PSv3+ equivalent, using an operation statement
      $output = (python --version 2>&1) | % ToString
      

    • 作为 Mathias R. Jessen 在对问题的评论中有注释,你自己也解释了版本, python 2.x条 -意外地-将其版本信息输出到 标准错误 而不是标准,不像 3.x条

    • $output = ... 是吗 分配 对变量的调用输出只捕获其 输出

    • 主要修复方法是使用重定向 2>&1 合并PowerShell的错误流(PowerShell的模拟到stderr,stderr输出映射到该流) 如果重定向 )输入PowerShell的成功输出流(stdout模拟),然后在变量中捕获。

      • 由于 重定向(默认情况下,stderr输出为 通过控制台 ), $? 总是设置为 $False ,因为向错误流写入任何内容都可以做到这一点(即使错误流最终被发送到其他地方,如本例中)。

        • $? 设置为 没有 an unfortunate discrepancy ),因为stderr输出永远不会“接触”PowerShell的错误输出流。
          在PowerShell控制台中,调用没有 2> 重定向, $? $错误 如果它是 退出代码 非零 ( $LASTEXITCODE -ne 0

        • 2>和1 在引入另一个问题的同时解决一个问题(无法捕获输出)( $? )-请参阅下面的补救措施。

      • 不是的 写入成功输出流 [System.Management.Automation.ErrorRecord] 实例,因为PowerShell将每个stderr输出行包装在一个实例中。

      • 如果您只在 一串 上下文-例如。, "Version: $output"

    • .ToString() (对于单个输出线)和 .ForEach('ToString') / (...) | % ToString (对于可能的多个输出行)撤消两个副作用:

      • [系统管理自动化[错误记录] 实例返回到

      • 它们重置了 $? $True .ToString() / .ForEach() 呼叫/使用 (...) 指挥部周围有 表达 ,它们本身被认为是成功的,即使它们包含 命令 他们自己设定的 $? $错误

    注:

    • 如果可执行 找不到,PowerShell本身将引发语句终止错误,这意味着 $输出 跳过 $? $错误 .

    • 如果 python 被调用和 --version ),如非零所示 退出代码 ,您可以通过自动 $LASTEXITCODE 变量(其值在下次调用 外部程序 ).

    • (...) $? 不变的回报 $正确 (除非发生语句或脚本终止错误)在上述方法中得到利用,但通常是模糊的行为,可能被认为是有问题的-请参阅 this discussion on GitHub .

    推荐文章