调用表达式,并非所有输出都返回到变量

时间:2019-08-25 16:37:35

标签: git powershell powershell-6.0

我在PowerShell脚本中使用了一些GIT命令。大多数情况下,我都是通过Invoke-Expression来调用GIT命令,例如,

  • 可以解析输出,或者/和
  • 将输出转发到日志记录方法。

在某些GIT命令中,我认识到尽管documentation指出,并非所有输出都通过Invoke-Expression返回:

  

输出

     

PSObject

     

返回由调用的命令生成的输出(Command参数的值)。

这里是一个例子:

> $x = iex "git fetch --all"
remote: Enumerating objects: 7, done.
remote: Counting objects: 100% (7/7), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 4 (delta 3), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (4/4), done.

$x的内容:

> $x
Fetching origin
Fetching upstream

因此主要信息不会返回到$x。我无法想象git fetch --all通过stderr返回主要信息(这没有道理...)。

我还找到了此PowerShell question,该文件尚未答复,使用的PowerShell版本为2。

使用的PowerShell版本:

> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      6.2.0
PSEdition                      Core
GitCommitId                    6.2.0
OS                             Microsoft Windows 10.0.18362
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

如何强制Invoke-Expression返回整个输出?

Thx

3 个答案:

答案 0 :(得分:3)

正如我在“ PowerShell Capture Git Output”中提到的那样,您可以尝试使用Git 2.16 (Q1 2018)进行设置:

set GIT_REDIRECT_STDERR=2>&1

然后在Powershell脚本中,您应该同时获得stdout和stderr输出,

有关更类似于Powershell的示例,另请参见dahlbyk/posh-git issue 109

$env:GIT_REDIRECT_STDERR = '2>&1'

答案 1 :(得分:2)

尝试此操作(不使用iex)

$x=git fetch --all

答案 2 :(得分:2)

VonC's answer特别适合git,但值得讨论通用解决方案


注意: Invoke-Expression should generally be avoided ,并且没有 没有理由使用它来调用外部程序:只需调用它们直接并分配给变量:

$capturedStdout = git ... # capture git's stdout output as an array of lines

如前所述, git状态信息输出到 stderr ,而 data 标准输出 PowerShell变量分配仅捕获 stdout 输出 [1]

要捕获交错的stdout和stderr的组合,因为它会打印到终端,所以可以使用重定向2>&1 将错误流/ stderr(2)合并到(>&)数据输出流中(等效于stdout,1-请参见about_Redirection ):

$combinedOutput = git fetch --all 2>&1 

注意事项:如果$ErrorActionPreference = 'Stop'生效,则2>的使用会意外触发终止错误; this GitHub issue中讨论了这种有问题的行为。

与其他外壳的行为没有明显差异,

  • 输出将是一个行数组 ,而不是单个多行字符串。

  • 如预期的那样,
  • 源自 stdout 的行被表示为 strings ,但是源自 stderr 的行实际上是{{1 }}实例,尽管它们像字符串一样 print 打印并在 conversion 上转换为字符串,但它们确实会重现原始行,例如将结果发送到外部程序时。

    < / li>

基于数组的结果可能有利于解析;例如,查找包含单词System.Management.Automation.ErrorRecord的行:

unpacking

如果您希望接收单个多行字符串,则可以:

PS> $combinedOutput -match 'unpacking'
Unpacking objects: 100% (4/4), done.

如果您不介意将尾随换行符作为字符串的一部分,则可以更简单地使用$combinedOutput = (git fetch --all 2>&1) -join "`n" # \n (LF); or: [Environment]::NewLine

Out-String

[1]有关在PowerShell中捕获来自外部程序的输出的全面信息,请参见this answer