Sle*_*led 4 terminal powershell tee windows-console
我正在编写一个脚本,我想传递这些值,但也想看到它们显示
Get-Content data.txt | Tee-Object | data_processor.exe
Run Code Online (Sandbox Code Playgroud)
但Tee-Object总是请求一个文件,我只想在屏幕上看到它。
为了补充zett42 的有用答案:
如果您运行的是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
# See coming future improvement below (-Host)
Get-Content data.txt | Tee-Object ($IsWindows ? '\\.\CON': '/dev/tty') | data_processor.exe
Run Code Online (Sandbox Code Playgroud)
笔记:
($IsWindows ? '\\.\CON': '/dev/tty')为-Host.这会传递所有数据,同时还将其打印到终端(控制台),像往常一样,在可用时进行丰富的格式化- 与该Tee-Object -Variable方法不同,该方法需要首先收集内存中的所有输出(这在输出方面都是一个问题)时间和内存消耗)。
Windows PowerShell解决方案:自定义代理(包装器)函数 Tee-Host进行包装Out-Host,同时传递其输入;使用它代替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()
  }
    
}
Run Code Online (Sandbox Code Playgroud)
实际上,Tee-Host其行为类似于PowerShell 7+ 中的Tee-Object \\.\CON/ ,也可以工作。Tee-Object /dev/ttyTee-Host
即使在 PowerShell 7+ 中也Tee-Host可能更可取,因为它无条件地使用彩色输出,而/的着色行为取决于Tee-Object \\.\CONTee-Object /dev/tty$PSStyle.OutputRendering
它使用具有可步进管道包装的代理函数Out-Host,确保到主机格式化的输出看起来与输入直接发送到主机时相同。
您可以输出到变量而不是文件:
Get-Content data.txt | Tee-Object -Variable data | data_processor.exe
$data  # Output
Run Code Online (Sandbox Code Playgroud)
这会将内容传递给“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
Run Code Online (Sandbox Code Playgroud)
通过编写一个小的过滤器函数,可以使该模式更加简洁和可重用:
Filter Write-HostAndForward {
    Write-Host $_   # Output line to console
    $_              # Forward line to next command in chain    
}
Run Code Online (Sandbox Code Playgroud)
现在我们可以写:
Get-Content data.txt | Write-HostAndForward | data_processor.exe
Run Code Online (Sandbox Code Playgroud)
评论:
虽然Write-HostAndForward适用于简单输入,例如从 接收的字符串Get-Content,但对于复杂对象,它通常不会产生与我们通常在控制台中看到的相同的输出。这是因为Write-Host只需使用该方法将输入转换为字符串.ToString(),从而跳过 PowerShell 丰富的格式系统。
您可能会想简单地替换Write-Host为Out-Host,但正如mklement0所解释的那样,它将单独格式化输入对象,这将为表格式输出的每个对象生成一个标头。为了避免这种情况,mklement0 的答案显示了生成预期格式化输出的不同方法。
|   归档时间:  |  
           
  |  
        
|   查看次数:  |  
           1634 次  |  
        
|   最近记录:  |