将获取内容管道化到自己的函数

use*_*625 2 powershell pipeline function

我正在尝试编写一个 powershell 函数,该函数通过管道从 get-content commandlet 接收文件列表并处理它们。管道看起来像这样:

get-content D:\filelist.txt | test-pipeline
Run Code Online (Sandbox Code Playgroud)

为了简单起见,下面的函数应该只显示文本文件的每一行。

function test-pipeline
{
<#
.Synopsis
#>

  [CmdletBinding( SupportsShouldProcess=$true)]

  Param([Parameter(Mandatory = $true,
                   ValueFromPipeLine = $true)]
        [array]$filelist

       )



    foreach ($item in $filelist)
    {
        $item
    }


}
Run Code Online (Sandbox Code Playgroud)

我的文件列表是一个普通的 .txt 文件,如下所示。

line 1
line 2
line 3
line 4
line 5
Run Code Online (Sandbox Code Playgroud)

无论我向函数传递什么类型的参数,它都不会起作用,并且仅在 $filelist 变量中显示文本文件的最后一行。有人可以帮忙吗?Powershell 版本是 v2 提前致谢

Mic*_*ens 5

您只看到最后一行的原因需要深入研究可管道的 PowerShell 函数的本质。在没有 Swonkie 提到的显式开始/处理/结束块的情况下,函数中的所有代码都像在end块中一样运行,即就像您编写的那样:

function test-pipeline
{
  [CmdletBinding()]
  Param(
    [Parameter(ValueFromPipeLine = $true)][array]$filelist
  )
  END {
    $filelist
  }
}
Run Code Online (Sandbox Code Playgroud)

但是,作为管道变量,当输入管道数据时,其中$filelist只有当前值;end块在管道输入耗尽时运行,因此$filelist仅包含最后一个值。只需将该end块更改为一个process块(它针对管道中的每个值运行)即可为您提供所需的输出:

function test-pipeline
{
  [CmdletBinding()]
  Param(
    [Parameter(ValueFromPipeLine = $true)][array]$filelist
  )
  PROCESS {
    $filelist
  }
}
Run Code Online (Sandbox Code Playgroud)

请注意,您不需要任何类型的循环——管道已经提供了“循环”。


这只是处理管道数据的几种方法之一。这是一个更接近的变体,它更短一些:使用filter代替function,因为filter没有显式块的操作就好像所有代码都在process块中一样。

filter test-pipeline
{
  [CmdletBinding()]
  Param(
    [Parameter(ValueFromPipeLine = $true)][array]$filelist
  )
  $filelist
}
Run Code Online (Sandbox Code Playgroud)

要进一步深入了解为管道编写函数的迷人而神秘的世界,请查看我撰写的深入分析,Down the Rabbit Hole: A Study in PowerShell Pipelines, Functions, andParameter,发表于 Simple-Talk.com 。享受您的 PowerShell 冒险吧!