管道数字阵列的Foreach没有正确破坏

时间:2016-04-29 17:56:38

标签: powershell foreach break pipeline

我不太明白这一点,但为什么以下代码不起作用:

"start"
1..5 | foreach {
    "$_"
    break
}
"stop"

我做了几次测试,这段代码运行正常:

"start"
foreach ($num in 1..5){
    "$num"
    break
}
"stop"

有没有办法让第一个例子正常运行?最后输出的行应该是“停止”。

像这样:

start
1
stop

1 个答案:

答案 0 :(得分:2)

首先,当您使用foreach ($thing in $things) {}$things | foreach { }时,您应该知道使用两种完全不同的语言功能。

第一个是内置的foreach语句,第二个是ForEach-Object的别名,它们的工作方式非常不同。

ForEach-Object为每个项运行脚本块,它在管道中运行。

在这种情况下,break语句只是break当前项目的执行。所谓的“父母”不会因为break而知道脚本块已退出并继续执行下一个对象的脚本块。

如何限制结果取决于你想做什么。

如果您只想停止生成结果,请在条件满足时不要返回任何内容。您仍将运行每次迭代,但结果将是正确的。

如果您只需要返回一定数量的项目,例如第一个N项目,那么最好的方式(从PowerShell v3开始)就是添加Select-Object

1..10 | ForEach-Object {
    $_*2
} | Select-Object -First 5

这只会执行5次,它将返回序列2,4,6,8,10

这是因为管道在每个对象通过每个cmdlet发送的位置如何工作,而Select-Object可以停止管道,因此它不会继续执行。

3.0版之前的版本,管道无法以这种方式停止,虽然结果是正确的,但您不会阻止额外的执行。

如果您提供有关退出条件的更多详细信息,我可以提供更多关于您希望如何处理该特定问题的信息(可能涉及不使用ForEach-Object)。