我正在编写脚本,希望能够传递值并在屏幕上显示出来。
Get-Content data.txt | Tee-Object | data_processor.exe
但是Tee-Object
总是要求一个文件,而我只想在屏幕上看到它。
我正在编写脚本,希望能够传递值并在屏幕上显示出来。
Get-Content data.txt | Tee-Object | data_processor.exe
但是Tee-Object
总是要求一个文件,而我只想在屏幕上看到它。
为了补充zett42的有帮助的答案:
如果你正在运行PowerShell(核心)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
将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()
}
}
实际上,Tee-Host
的行为类似于 PowerShell 7+ 中的 Tee-Object \\.\CON
/ Tee-Object /dev/tty
,其中 Tee-Host
也可以工作。
即使在 PowerShell 7+ 中,Tee-Host
也可能更可取,因为它无条件地使用了 彩色 输出,而 Tee-Object \\.\CON
/ Tee-Object /dev/tty
的着色行为取决于 $PSStyle.OutputRendering
的值。
使用包装 Out-Host
的可步进管道的代理函数确保了发送到主机时格式化输出的外观与直接发送输入时相同。
Get-Content data.txt | Tee-Object -Variable data | data_processor.exe
$data # Output
这将内容传递给"data_processor.exe"并将其存储在变量$data
中。只有当.exe完成后,数据才会显示。
使用ForEach-Object
检查Get-Content
的输出,在每行发送到.exe之前进行:
Get-Content data.txt | ForEach-Object {
Write-Host $_ # Output line to console
$_ # Forward line to next command in chain
} | data_processor.exe
通过编写一个小的筛选函数,可以使这个模式更加简洁和可重复利用:
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 的丰富格式化系统。
你可能会尝试简单地将 Write-Host
替换为 Out-Host
,但正如 mklement0 解释的那样,它会分别对输入对象进行格式化,这将为表格格式的输出每个对象产生一个标题。为了避免这种情况,mklement0 的答案展示了不同的方法来产生期望的格式化输出。
Tee-Object
所做的事情,尽管我可以理解为什么你会这样认为。你可能需要用ForEach-Object{Write-Host $_; $_}
替换它,并通过循环运行所有内容。 - TheMadTechnicianGet-Content
上使用-raw
开关。这将读取整个文件,然后可以将其传递到ForEach-Object
循环中,其中所有四行将被写入主机并一次传递给data_processor.exe
。或者在| data_processor.exe
之前将所有内容包含在括号中。 - TheMadTechnician