您可以将 Tee-Object 重定向到标准输出吗?

Can you redirect Tee-Object to standard out?

我正在编写脚本,我想传递这些值,但也想看到它们显示出来

Get-Content data.txt | Tee-Object | data_processor.exe

但是Tee-Object总是请求一个文件,而我只想在屏幕上看到它。

您可以输出到变量而不是文件:

Get-Content data.txt | Tee-Object -Variable data | data_processor.exe
$data  # Output

这会将内容传递给“data_processor.exe”并将其存储在变量$data 中。只有在 .exe 完成后才会显示数据。

在将每一行发送到 .exe 之前,使用 ForEach-Object 检查 Get-Content 的输出:

Get-Content data.txt | ForEach-Object {
    Write-Host $_   # Output line to console
    $_              # Forward line to next command in chain 
} | data_processor.exe

可以通过编写一个小 filter function:

使此模式更加简洁和可重用
Filter Write-HostAndForward {
    Write-Host $_   # Output line to console
    $_              # Forward line to next command in chain    
}

现在我们可以写:

Get-Content data.txt | Write-HostAndForward | data_processor.exe

备注:

虽然 Write-HostAndForward 适用于简单的输入,例如从 Get-Content 接收的字符串,但对于复杂的对象,它通常不会产生与我们通常在控制台中看到的相同的输出。这是因为 Write-Host 只是使用 .ToString() 方法将输入转换为字符串,这会跳过 PowerShell 的富格式系统。

您可能想简单地用 Out-Host 替换 Write-Host,但是 mklement0 explains, it would format the input objects individually, which will produce a header for each object for table-formatted output. To avoid that, 显示了生成预期格式化输出的不同方法。

补充

如果你是运行PowerShell (Core) 7+,你可以传递代表终端的文件路径(控制台) 到(位置隐含的)-FilePath 参数(在 Windows PowerShell 中,不幸的是,这会导致错误- 见底部):

# PowerShell 7+ only

# Windows
Get-Content data.txt | Tee-Object CON | data_processor.exe

# Unix-like platforms (Linux, macOS)
Get-Content data.txt | Tee-Object /dev/tty | data_processor.exe

# Platform-agnostic
Get-Content data.txt | Tee-Object ($IsWindows ? 'CON': '/dev/tty') | data_processor.exe

传递所有数据,同时还将其打印到终端(控制台),格式丰富,像往常一样,可用时 - 与 Tee-Object -Variable 方法不同,后者需要首先在内存中收集所有输出(这在输出时间和内存消耗方面都是一个问题)。


Windows PowerShell 解决方案:自定义 Tee-Host wraps Out-Host 同时也传递其输入;使用它 代替 of Tee-Object:

function Tee-Host {  
  [CmdletBinding()]
  param(
    [Parameter(ValueFromPipeline)] $InputObject
  )

  begin
  {
    $scriptCmd = { Out-Host }
    $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
    $steppablePipeline.Begin($PSCmdlet)
  }
  
  process
  {
    # Pass to Out-Host, and therefore to the host (terminal)
    $steppablePipeline.Process($InputObject)
    # Pass through (to the success stream)
    $InputObject 
  }
  
  end
  {
    $steppablePipeline.End()
  }
    
}
  • 实际上,Tee-Host 的行为类似于 PowerShell 7+ 中的 Tee-Object CON / Tee-Object /dev/tty,其中 Tee-Host 也有效。

  • 即使在 PowerShell 7+ 中,Tee-Host 可能更可取,因为它使用 colored 输出 unconditionally ,而 Tee-Object CON / Tee-Object /dev/tty 的着色行为取决于 $PSStyle.OutputRendering

    的值

使用代理函数和可步进管道包装 Out-Host 确保 to-host 格式化输出看起来与输入直接发送到主机时相同。