【问题标题】:Powershell: Supress the output to console if it is pipelinedPowershell:如果是流水线的,则将输出抑制到控制台
【发布时间】:2016-11-29 17:06:51
【问题描述】:

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

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

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

我想要这样的输出:

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 来做到这一点?

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

提前谢谢你

【问题讨论】:

    标签: powershell return output suppress


    【解决方案1】:

    回答问题

    有没有办法在函数本身中确定返回值是否是流水线的?

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

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

    原答案如下。


    非常简单的解决方案:

    不要在你的脚本中使用Write-Host

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

    如果您需要保留这些语句以进行调试,请改用 Write-DebugWrite-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++
    }
    

    然后使用like:

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

    【讨论】:

    • 非常感谢您的回复,但很抱歉,也许我的问题没有自我解释。我必须使用写主机,因为它为用户提供数据。我真正要问的是有没有办法在函数本身中确定返回值是否是流水线的?我需要增加 $PrevRes 值进行计算,但是当它不再流水线化时,我不想将它输出到屏幕上。因此,我只需要 alfa beta 和 omega,最后没有数字。
    • @SokIsKedu 我不确定你所说的“如果返回值是流水线的”是什么意思——在 PowerShell 中,一个函数发出 0 个或多个对象,最后一个是在 return 语句之后。如果管道中的下一件事是另一个函数,则对象将被发送到它,否则返回给调用者
    • 如果你的客户“不知道怎么用”,那他为什么要你送货呢?
    • 那么我要问的是有没有办法抑制返回值?就像我将它传递给另一个函数一样,我可以用它进行计算,但如果不是,我不希望将返回值放在屏幕上。好吧,客户对 powershell 和管道有一定的了解,但如果他需要添加更多内容,他将不会满意。
    • 哦,我写错了标题,漏掉了not这个词。它应该像 Powershell:如果不是流水线,则将输出抑制到控制台
    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 2011-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多