为什么继续像在一个Foreach对象中的行为一样?

如果我在PowerShell脚本中执行以下操作:

$range = 1..100 ForEach ($_ in $range){ if ($_ % 7 -ne 0 ) { continue; } Write-Host "$($_) is a multiple of 7" } 

我得到了预期的输出:

 7 is a multiple of 7 14 is a multiple of 7 21 is a multiple of 7 28 is a multiple of 7 35 is a multiple of 7 42 is a multiple of 7 49 is a multiple of 7 56 is a multiple of 7 63 is a multiple of 7 70 is a multiple of 7 77 is a multiple of 7 84 is a multiple of 7 91 is a multiple of 7 98 is a multiple of 7 

但是,如果我使用pipe道和ForEach-Object ,继续似乎突破stream水线循环。

 1..100 | ForEach-Object { if ($_ % 7 -ne 0 ) { continue; } Write-Host "$($_) is a multiple of 7" } 

我的问题是,在继续执行ForEach-Object的过程中,是否可以继续进行类似的行为,所以我不必分裂我的pipe道?

只需使用return而不是continue 。 这个返回从ForEach-Object在特定迭代中调用的脚本块返回,因此它模拟循环中的continue

 1..100 | ForEach-Object { if ($_ % 7 -ne 0 ) { return } Write-Host "$($_) is a multiple of 7" } 

这是重构时要牢记的一个问题。 有时候,我们想用一个ForEach-Object cmdlet将一个foreach语句块转换成一个pipe道(它甚至有别名foreach ,这使得这个转换变得简单,而且容易出错)。 所有的continue应该被replace为return

PS不幸的是,在ForEach-Object模拟break并不容易。

因为For-Each对象是一个cmdlet而不是一个循环,continue / break不适用于它。

例如,如果您有:

 $b = 1,2,3 foreach($a in $b){ $a | foreach { if($_ -eq 2) {continue;} else {write-host $_} } write-host "after" } 

你会得到如下输出:

 1 after 3 after 

这是因为continue会应用到外部foreach循环而不是foreach-object cmdlet。 没有一个循环,最外层的水平,因此给你一个印象,就像打破。

那么,你如何继续像行为? 其中一种方式就是在哪里 –

 1..100 | ?{ $_ % 7 -eq 0} | %{write-host $_ is a mutliple of 7} 

另一种方法是黑客攻击,但是你可以把你的代码块放在一个循环中执行一次,这样就可以继续执行预期的效果:

 1..100 | ForEach-Object { for($cont=$true;$cont;$cont=$false){ if ($_ % 7 -ne 0 ) { continue; } Write-Host "$($_) is a multiple of 7" } }