gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-03 01:03:53 25 4
gpt4 key购买 nike

通常,我知道如何将命令的输出捕获到Powershell中的变量中:

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

Python 3打印其版本,但是将其捕获到变量 $output中,并且控制台上未显示任何内容。如预期的那样:
> $output = python3 --version
> Write-Host $output
Python 3.7.0

但是对于Python 2,它不起作用。 Python 2打印其版本,但其在控制台上显示而不是捕获,并且变量 $output为空。
> $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:
>

Python 2如何打印未捕获到变量的版本,并且有可能以任何方式捕获它?

最佳答案

这是由 Python 2引起的,该Python 2将版本打印到stderr而不是stdout 。程序调用输出的分配仅捕获stdout,在这种情况下为空。另一方面,默认情况下将stderr打印到控制台,这就是为什么$output变量为空并且将版本打印到控制台的原因。有关详情,请参见下文。

tl;博士:

# 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

对于可能返回多个stderr行的命令,请使用:
  • PSv4 +,使用.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将其版本信息输出到stderr 而不是stdout,与3.x不同。
  • 之所以无法使用$output = ...捕获输出,是因为将外部程序调用的输出分配给变量时,默认情况下仅捕获其stdout输出
  • 使用PowerShell本地命令,它捕获命令的成功输出流-请参阅about_redirection
  • 的主要修补程序是使用重定向2>&1 将PowerShell的错误流(PowerShell的模拟流与stderr合并,如果重定向到stderr,则将stderr输出映射到)合并到PowerShell的成功输出流(stdout类似物)中,然后将其捕获到变量中。
    但是,这有两个副作用:
  • 由于PowerShell的错误流现在由于2>&1重定向而涉及到(默认情况下,stderr输出会传递到控制台),因此 $?始终设置为$False ,因为向错误流写入任何内容都会做到这一点(即使错误流最终发送到其他地方(在这种情况下)。
  • 请注意,不进行重定向,就不会将$?设置为$False(在ISE中除外,它是an unfortunate discrepancy),因为stderr输出从不会“接触” PowerShell的错误输出流。
    在PowerShell控制台中,当调用没有2>重定向的外部程序时,仅当其退出代码为非零($?)时,$False才设置为$LASTEXITCODE -ne 0
  • 因此,使用2>&1可以解决一个问题(无法捕获输出),同时引入另一个问题($?错误地设置为$False)-请参见下文以寻求解决方法。
  • 写入成功输出流的不是字符串,而是[System.Management.Automation.ErrorRecord]实例,因为PowerShell将每条stderr输出行都包装为一个。
  • 如果您仅在字符串上下文中使用这些实例(例如"Version: $output"),则可能不会注意到或不在意。
  • .ToString()(用于单个输出行)和.ForEach('ToString') / (...) | % ToString(用于潜在的多个输出行)都消除了以下两种副作用:
  • 他们将[System.Management.Automation.ErrorRecord]实例转换回字符串。
  • 他们将$?重置为$True,因为.ToString() / .ForEach()调用/在命令周围使用(...)是表达式,即使它们本身包含将$?设置为$False的命令,它们也被认为是成功的。

  • 注意:
  • 如果无法找到可执行文件python,PowerShell本身将引发语句终止错误,这意味着将跳过对$output的分配(其值(如果存在)将保持不变),并且默认情况下,您会得到嘈杂的错误输出,并且$?将设置为$False
  • 如果可以调用python并报告错误(--version不太可能发生)(如非零退出代码所示),则可以通过自动$LASTEXITCODE变量检查该退出代码(其值在下一次调用ant之前不会更改。外部程序)。
  • 在上述方法中可以利用诸如将(...)放在命令周围这样简单的操作使$?始终返回$True(除非发生语句或脚本终止错误的情况除外)的方法,但通常这种模糊的行为可能会引起问题-请参见this discussion on GitHub
  • 关于powershell - 打印命令输出而不是在Powershell中捕获,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52099888/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com