为什么在 Foreach 对象中“ Continute”的行为类似于“ break”?

如果我在 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

但是,如果我使用管道和 ForEach-Objectcontinue似乎打破了管道循环。

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

在执行 Foreach-Object 的同时,是否可以获得类似 continue的行为,这样就不必中断管道?

87571 次浏览

因为 For-Each对象是一个 cmdlet 而不是一个循环,并且 continuebreak不适用于它。

例如:

$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。在没有循环的情况下,最外层,因此给您一种它像 break一样工作的印象。

那么如何获得类似 continue的行为呢? 一种方法当然是 哪里-目标:

1..100 | ?{ $_ % 7  -eq 0} | %{Write-Host $_ is a multiple of 7}

另一种替代方法是一种黑客技术,但是您可以将块包装在一个循环中,该循环只执行一次。这样,continue就能达到预期效果:

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

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

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

在进行重构时,需要记住一个问题。有时候,人们希望将 foreach语句块转换为具有 ForEach-Object cmdlet 的管道(它甚至具有别名 foreach,这有助于使转换变得容易,也容易出错)。所有的 continue都应该用 return代替。

附注: 不幸的是,在 ForEach-Object中模拟 break并不那么容易。

一个简单的 else语句使其工作原理如下:

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

或者在一个单一的管道中:

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

但是一个更优雅的解决方案是反转您的测试并只为您的成功生成输出

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