ForEach-Object是对管道中的单个对象还是对象集合进行操作?

Sim*_*wsi 3 powershell pipeline

我很难掌握PowerShell管道的工作方式,并且我意识到很多问题都是由于ForEach-Object.在我使用的其他语言中,foreach在一个集合上运行,依次遍历集合的每个元素.我假设ForEach-Object,在PowerShell管道中使用时,也会这样做.但是,我读到的有关管道的所有内容都表明集合的每个元素都是分别通过管道传递的,并且重复调用下游cmdlet,分别对每个元素进行操作,而不是整个集合.

那么ForEach-Object对集合中的单个元素进行操作,而不是整个集合上的操作吗?以不同的方式查看它,管道操作符是否通过整个集合ForEach-Object,然后迭代它,或者管道对象是否迭代集合并将每个元素分别传递给ForEach-Object

mkl*_*nt0 7

ForEach-Objectcmdlet的 -不像foreach 声明 -本身执行枚举.

相反,它对通过管道传递的每个项目进行操作(可选择在接收第一个项目之前和接收到最后一个项目之后执行代码,如果有的话).

因此,它可以说是命名不佳,因为它是提供枚举的管道(默认情况下),并且ForEach-Object只是为每个接收的项调用一个脚本块.

以下示例说明了这一点:

# Let the pipeline enumerate the elements of an array:
> 1, 2 | ForEach-Object { "item: [$_]; count: $($_.Count)" }
item: [1]; count: 1
item: [2]; count: 1

# Send the array *as a whole* through the pipeline (PSv4+)
> Write-Output -NoEnumerate 1, 2 | ForEach-Object { "item: [$_]; count: $($_.Count)" }
item: [1 2]; count: 2
Run Code Online (Sandbox Code Playgroud)

请注意,脚本/函数/ cmdlet可以选择是否应枚举写入输出流(管道)的集合作为整体(作为单个对象).

在PowerShell代码(脚本或函数,无论是否为高级(cmdlet))中,枚举是默认值,但您可以选择退出Write-Output -NoEnumerate;该-NoEnumerate开关是在PSv4中引入的;在此之前,您必须使用$PSCmdlet.WriteObject(),这只是可用的以先进的脚本/功能.

另请注意,通过将命令括在强制枚举中(...),将命令嵌入到表达式:

# Send array as a whole.
> Write-Output -NoEnumerate 1, 2 | Measure-Object

Count: 1
...

# Converting the Write-Output -NoEnumerate command to an expression
# by enclosing it in in (...) forces enumeration
> (Write-Output -NoEnumerate 1, 2) | Measure-Object

Count: 2
...
Run Code Online (Sandbox Code Playgroud)