PowerShell: the mysterious -RemainingScripts parameter of ForEach-Object

前端 未结 5 2102
闹比i
闹比i 2021-02-08 00:21

Short question: anyone has detailed information on -RemainingScripts parameter of ForEach-Object?

Long question:

I just started

5条回答
  •  野趣味
    野趣味 (楼主)
    2021-02-08 01:09

    Here are some more examples that support @FangZhou's ordering hypothesis.

    If you specify the other blocks, it seems to make sense how it works:

    PS C:\> 1..5 | ForEach-Object -Begin { "Begin: $_" } -End { "End: $_" } -Process { "Process: $_" } -RemainingScripts { "R1: $_" },{ "R2: $_" },{ "R3: $_" }
    Begin: 
    Process: 1
    R1: 1
    R2: 1
    R3: 1
    Process: 2
    R1: 2
    R2: 2
    R3: 2
    Process: 3
    R1: 3
    R2: 3
    R3: 3
    Process: 4
    R1: 4
    R2: 4
    R3: 4
    Process: 5
    R1: 5
    R2: 5
    R3: 5
    End: 
    

    Even if you pass empty blocks:

    PS C:\> 1..5 | ForEach-Object -Begin {} -End {} -Process { "Process: $_" } -RemainingScripts { "R1: $_" },{ "R2: $_" },{ "R3: $_" }
    Process: 1
    R1: 1
    R2: 1
    R3: 1
    Process: 2
    R1: 2
    R2: 2
    R3: 2
    Process: 3
    R1: 3
    R2: 3
    R3: 3
    Process: 4
    R1: 4
    R2: 4
    R3: 4
    Process: 5
    R1: 5
    R2: 5
    R3: 5
    

    However, if you don't specify -End, it does something completely different. The last scriptblock passed to the command is used for -End.

    PS C:\> 1..5 | ForEach-Object -Begin { "Begin: $_" } -Process { "Process: $_" } -RemainingScripts { "R1: $_" },{ "R2: $_" },{ "R3: $_" }
    Begin: 
    Process: 1
    R1: 1
    R2: 1
    Process: 2
    R1: 2
    R2: 2
    Process: 3
    R1: 3
    R2: 3
    Process: 4
    R1: 4
    R2: 4
    Process: 5
    R1: 5
    R2: 5
    R3: 
    

    And you can change what happens by changing the order of properties:

    PS C:\> 1..5 | ForEach-Object  -RemainingScripts { "R1: $_" },{ "R2: $_" },{ "R3: $_" } -Begin { "Begin: $_" } -Process { "Process: $_" }
    Begin: 
    R1: 1
    R2: 1
    R3: 1
    R1: 2
    R2: 2
    R3: 2
    R1: 3
    R2: 3
    R3: 3
    R1: 4
    R2: 4
    R3: 4
    R1: 5
    R2: 5
    R3: 5
    Process: 
    

    And if you don't specify -Begin, it's different again. Now the first scriptblock passed is used for -Begin:

    PS C:\> 1..5 | ForEach-Object -End { "End: $_" } -Process { "Process: $_" } -RemainingScripts { "R1: $_" },{ "R2: $_" },{ "R3: $_" }
    Process: 
    R1: 1
    R2: 1
    R3: 1
    R1: 2
    R2: 2
    R3: 2
    R1: 3
    R2: 3
    R3: 3
    R1: 4
    R2: 4
    R3: 4
    R1: 5
    R2: 5
    R3: 5
    End: 
    

    If you specify neither -Begin nor -End, it combines the two. Now the first scriptblock replaces -Begin and the last scriptblock of replaces -End:

    PS C:\> 1..5 | ForEach-Object -Process { "Process: $_" } -RemainingScripts { "R1: $_" },{ "R2: $_" },{ "R3: $_" }
    Process: 
    R1: 1
    R2: 1
    R1: 2
    R2: 2
    R1: 3
    R2: 3
    R1: 4
    R2: 4
    R1: 5
    R2: 5
    R3: 
    

    As far as I can tell, it's intended to support positional scriptblocks, where you're going to write:

    1..5 | ForEach-Object { "Begin: $_" } { "Process1: $_" } { "Process2: $_" } { "Process3: $_" } { "End: $_" }
    

    Or like so:

    1..5 | ForEach-Object { "Begin: $_" },{ "Process1: $_" },{ "Process2: $_" },{ "Process3: $_" },{ "End: $_" }
    

    Both of which output:

    Begin: 
    Process1: 1
    Process2: 1
    Process3: 1
    Process1: 2
    Process2: 2
    Process3: 2
    Process1: 3
    Process2: 3
    Process3: 3
    Process1: 4
    Process2: 4
    Process3: 4
    Process1: 5
    Process2: 5
    Process3: 5
    End: 
    

提交回复
热议问题