选择对象使用管道与-InputObject的行为不同

Bra*_*d_Z 1 powershell

有人可以说明为什么示例2与示例1的结果不同吗?我认为$ a和$ b2应该相同。$ b2为空!我正在编写一个脚本,其中最好使用示例2中的方法。

范例1:

$a = Get-Content $some_text_file | Select-Object -Skip 1
Run Code Online (Sandbox Code Playgroud)

范例2:

$b1 = Get-Content $some_text_file
$b2 = Select-Object -InputObject $b1 -Skip 1
Run Code Online (Sandbox Code Playgroud)

编辑:使用此语法可以使我到达需要的位置。

$b1 = Get-Content $file
$b2 = $b1 | Select-Object -Skip 1
Run Code Online (Sandbox Code Playgroud)

Mat*_*sen 5

Lee_Dailey所述,这是预期的行为

有人可以阐明为什么

这与cmdlet在管道中的执行方式有关。

您可能知道,cmdlet的核心功能由三种方法组成:

*(高级功能中的begin/ process/ end块与此相对应)。

BeginProcessing()并且EndProcessing()总是执行一次ProcessRecord()执行多少次取决于它是否是管道中的第一个命令。

当cmdlet作为管道中的第一个元素出现时(即|,它的左侧没有符号),将ProcessRecord()执行一次

但是,当cmdlet从其管道中的上游命令接收输入时,将对通过管道进入的每个输入项ProcessRecord()运行一次

考虑到这一点,请考虑以下简化版本Select-Object

function Select-FakeObject {
    param(
        [Parameter(Mandatory, ValueFromPipeline)]
        [object[]]$InputObject,

        [Parameter()]
        [int]$Skip = 0
    )

    begin {
        $skipped = 0
    }

    process {
        if($skipped -lt $Skip){
            $skipped++
            Write-Host "Skipping $InputObject"
        }
        else{
            Write-Host "Selecting $InputObject"
            Write-Output $InputObject
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,让我们使用此虚拟函数尝试两种情况:

PS C:\> $a = 1,2,3
PS C:\> $b1 = $a |Select-FakeObject -Skip 1
Run Code Online (Sandbox Code Playgroud)

我们将看到PowerShell确实对每个输入项调用一次process块:

Skipping 1
Selecting 2
Selecting 3
Run Code Online (Sandbox Code Playgroud)

而如果我们像您的第二个示例那样传递对象:

PS C:\> $a = 1,2,3
PS C:\> $b2 = Select-FakeObject -Skip 1
Skipping 1 2 3
Run Code Online (Sandbox Code Playgroud)

现在,我们看到该process块仅对全部$a而不是单个项目执行一次。