我应该如何使用Write-Host以使管道和参数输入的行为方式相同?

时间:2014-08-27 20:22:47

标签: powershell foreach pipeline

我有一个PowerShell脚本,它接受管道输入,处理每个项目,然后在每个项目上调用Write-Host

当我使用参数输入调用脚本时,我的foreach循环会写出一个标题行,然后是它下面的数据。当通过管道调用时,我为每行输入获得一个标题行和一个数据行。我想PowerShell有一些代码可以解释当你在Write-Host循环中执行foreach并且在这种情况下只写入一次头。

所以我的问题是,我应该如何解决这个问题,以便两种形式的输入之间的行为一致?我确定我做错了,但我不知道正确的方法。

这是我的剧本。

param (
    [Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)]
    [PSObject[]] $InputObject
)

process {
    $lines = ($InputObject | Out-String) -replace "`r", "" -split "`n"

    foreach ($line in $lines) {
        #Process $line here

        Write-Host $line
    }
}

以下是两个示例输出

MyScript.ps1 $(ps | Select-Object -First 10)

$(ps | Select-Object -First 10) | MyScript.ps1

1 个答案:

答案 0 :(得分:0)

我认为这是采用管道输入的cmdlet的设计行为。当输入是流水线时,每个对象都被单独处理,但如果您将集合作为InputObject传递,则集合将被视为单个对象。

您可以使用Select-Object进行尝试。

之间存在明显差异
ps | Select -First 1

Select -First 1 -InputObject (ps)

在您的情况下,流水线操作会导致每个对象在字符串处理步骤中运行,该步骤会为其打印标题。但是,当您使用InputObject参数时,集合将发送到Out-String,从而生成单个标头。

要使您的功能与其他cmdlet和函数保持一致,您应该设计流程步骤以处理流水线输入中的单个项目。否则,请准备好处理将集合作为单个对象的情况。

对此有一个开放的connect issue,但我怀疑它会得到修复,因为它是设计的行为,我相信。看起来在较新版本的PowerShell中,它们只是澄清了帮助中的实际行为。来自PowerShell 4中Select-Object的帮助:

  

当您将InputObject参数与Select-Object一起使用时,而不是将命令结果传递给Select-Object,而不是InputObject值 - 即使该值是作为命令结果的集合,例如-InputObject(Get-过程) - 被视为单个对象。

此外,通常当你有InputObject时,它的类型只是PSObject,而不是数组。