Powershell:如果是流水线,则将输出抑制到控制台

Powershell: Supress the output to console if it is pipelined

我正在 Powershell 上编写一个搜索工具,我 运行 遇到一个问题,我无法抑制函数的 return,它总是打印到控制台。 为了清楚起见,我做了一些较小的测试功能。

Function test1
{
    param(
    [Parameter(Mandatory=$false,ValueFromPipeline=$True)]
    $PrevRes = 0)
    write-host "alfa"
    return ($PrevRes+1)
}

Function test2
{
 param(
    [Parameter(Mandatory=$false,ValueFromPipeline=$True)]
    $PrevRes = 0)
    write-host "beta"
    return ($PrevRes+1) 
}

Function test3
{
 param(
    [Parameter(Mandatory=$false,ValueFromPipeline=$True)]
    $PrevRes = 0)
    write-host "omega"
    return ($PrevRes+1)
}

test1 gives:  
alfa
1

when test1 | test2:
alfa
beta
2

when test | test2 | test3:
alfa
beta
omega
3

when test | test3 | test2:
alfa
omega
beta
3

问题是我不知道这些函数的调用顺序是什么,我需要的是确保如果最后没有管道,return 就不会打印到屏幕上,但我仍然需要访问值本身。

我想要这样的输出:

test1 gives:  
alfa


when test1 | test2:
alfa
beta


when test | test2 | test3:
alfa
beta
omega


when test | test3 | test2:
alfa
omega
beta

这是一个为客户提供的工具,因此解决方案如下:

$tst = test1 |test2

不好,因为你知道,客户就是客户,他不会知道如何使用它。

有没有办法用我在网上错过的powershell来做?

如果不涉及客户的任何操作,任何解决方案都是有用的

提前致谢

回答问题

is there a way to determine in the function itself if the return value is pipelined or not?

是的。检查 $MyInvocation 自动变量并比较 PipelineLengthPipelinePosition 属性:

if($MyInvocation.PipelinePosition -lt $MyInvocation.PipelineLength){
    return $PrevRes + 1
}

原回答如下。


非常简单的解决方案:

不要在脚本中使用 Write-Host

顾名思义,它将写入内容直接到主机应用程序

如果出于调试目的需要保留这些语句,请改用 Write-Debug or Write-Verbose cmdlet:

function test1
{
    param(
    [Parameter(Mandatory=$false,ValueFromPipeline=$True)]
    $PrevRes = 0)
    Write-Verbose "alfa"
    return ($PrevRes+1)
}

function test2
{
 param(
    [Parameter(Mandatory=$false,ValueFromPipeline=$True)]
    $PrevRes = 0)
    Write-Verbose "beta"
    return ($PrevRes+1) 
}

function test3
{
 param(
    [Parameter(Mandatory=$false,ValueFromPipeline=$True)]
    $PrevRes = 0)
    Write-Verbose "omega"
    return ($PrevRes+1)
}

如果您需要在 cmdlet 之间增加 $PrevRes 值,您可以使用调用范围中的变量(尽管这有点反模式,我强烈建议不要这样做):

function test1 {
  Write-Host 'alpha'
  $global:PrevRes++
}

function test2 {
  Write-Host 'beta'
  $global:PrevRes++
}

function test3 {
  Write-Host 'omega'
  $global:PrevRes++
}

然后像这样使用:

PS> test1; test2; test3
alpha
beta
omega
PS> $PrevRes
3

@Mathias 是正确的,但从您的问题的外观来看,您正在使用 Write-Host 输出作为用户的实际 return 值,而不是实际 returning 数据。在这种情况下,你真的想做更像这样的事情。但正如已经说过的,不要将 Write-Host 用于脚本早期 development/debugging 之外的任何内容。

Function test1
{
  param(
  [Parameter(Mandatory=$false,ValueFromPipeline=$True)]
  $PrevRes = @())
  $PrevRes += 'alpha'
  return ($PrevRes)
}